mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-02-07 10:07:48 +00:00
Add more iteration method tests.
This commit is contained in:
287
test/test.js
287
test/test.js
@@ -4962,6 +4962,7 @@
|
|||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
var methods = [
|
var methods = [
|
||||||
|
'_baseEach',
|
||||||
'countBy',
|
'countBy',
|
||||||
'every',
|
'every',
|
||||||
'filter',
|
'filter',
|
||||||
@@ -4971,6 +4972,7 @@
|
|||||||
'findLast',
|
'findLast',
|
||||||
'findLastIndex',
|
'findLastIndex',
|
||||||
'findLastKey',
|
'findLastKey',
|
||||||
|
'forEach',
|
||||||
'forEachRight',
|
'forEachRight',
|
||||||
'forIn',
|
'forIn',
|
||||||
'forInRight',
|
'forInRight',
|
||||||
@@ -4995,6 +4997,7 @@
|
|||||||
];
|
];
|
||||||
|
|
||||||
var collectionMethods = [
|
var collectionMethods = [
|
||||||
|
'_baseEach',
|
||||||
'countBy',
|
'countBy',
|
||||||
'every',
|
'every',
|
||||||
'filter',
|
'filter',
|
||||||
@@ -5022,6 +5025,7 @@
|
|||||||
];
|
];
|
||||||
|
|
||||||
var iterationMethods = [
|
var iterationMethods = [
|
||||||
|
'_baseEach',
|
||||||
'forEach',
|
'forEach',
|
||||||
'forEachRight',
|
'forEachRight',
|
||||||
'forIn',
|
'forIn',
|
||||||
@@ -5066,35 +5070,75 @@
|
|||||||
|
|
||||||
_.each(methods, function(methodName) {
|
_.each(methods, function(methodName) {
|
||||||
var array = [1, 2, 3],
|
var array = [1, 2, 3],
|
||||||
func = _[methodName];
|
func = _[methodName],
|
||||||
|
isFind = /^find/.test(methodName),
|
||||||
|
isSome = methodName == 'some';
|
||||||
|
|
||||||
test('`_.' + methodName + '` should provide the correct `iteratee` arguments', 1, function() {
|
test('`_.' + methodName + '` should provide the correct `iteratee` arguments', 1, function() {
|
||||||
var args,
|
if (func) {
|
||||||
expected = [1, 0, array];
|
var args,
|
||||||
|
expected = [1, 0, array];
|
||||||
|
|
||||||
func(array, function() {
|
func(array, function() {
|
||||||
args || (args = slice.call(arguments));
|
args || (args = slice.call(arguments));
|
||||||
});
|
});
|
||||||
|
|
||||||
if (_.includes(rightMethods, methodName)) {
|
if (_.includes(rightMethods, methodName)) {
|
||||||
expected[0] = 3;
|
expected[0] = 3;
|
||||||
expected[1] = 2;
|
expected[1] = 2;
|
||||||
|
}
|
||||||
|
if (_.includes(objectMethods, methodName)) {
|
||||||
|
expected[1] += '';
|
||||||
|
}
|
||||||
|
deepEqual(args, expected);
|
||||||
}
|
}
|
||||||
if (_.includes(objectMethods, methodName)) {
|
else {
|
||||||
expected[1] += '';
|
skipTest();
|
||||||
}
|
}
|
||||||
deepEqual(args, expected);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('`_.' + methodName + '` should support the `thisArg` argument', 2, function() {
|
test('`_.' + methodName + '` should support the `thisArg` argument', 2, function() {
|
||||||
var actual,
|
if (methodName != '_baseEach') {
|
||||||
callback = function(num, index) { actual = this[index]; };
|
var actual,
|
||||||
|
callback = function(num, index) { actual = this[index]; };
|
||||||
|
|
||||||
func([1], callback, [2]);
|
func([1], callback, [2]);
|
||||||
strictEqual(actual, 2);
|
strictEqual(actual, 2);
|
||||||
|
|
||||||
func({ 'a': 1 }, callback, { 'a': 2 });
|
func({ 'a': 1 }, callback, { 'a': 2 });
|
||||||
strictEqual(actual, 2);
|
strictEqual(actual, 2);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
skipTest(2);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test('`_.' + methodName + '` should treat sparse arrays as dense', 1, function() {
|
||||||
|
if (func) {
|
||||||
|
var array = [1];
|
||||||
|
array[2] = 3;
|
||||||
|
|
||||||
|
var expected = [[1, 0, array], [undefined, 1, array], [3, 2, array]];
|
||||||
|
if (_.includes(objectMethods, methodName)) {
|
||||||
|
expected = _.map(expected, function(args) {
|
||||||
|
args[1] += '';
|
||||||
|
return args;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (_.includes(rightMethods, methodName)) {
|
||||||
|
expected.reverse();
|
||||||
|
}
|
||||||
|
var actual = [];
|
||||||
|
func(array, function(value, key, array) {
|
||||||
|
actual.push([value, key, array]);
|
||||||
|
return !(isFind || isSome);
|
||||||
|
});
|
||||||
|
|
||||||
|
deepEqual(actual, expected);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
skipTest();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -5106,22 +5150,28 @@
|
|||||||
array.a = 1;
|
array.a = 1;
|
||||||
|
|
||||||
test('`_.' + methodName + '` should not iterate custom properties on arrays', 1, function() {
|
test('`_.' + methodName + '` should not iterate custom properties on arrays', 1, function() {
|
||||||
var keys = [];
|
if (func) {
|
||||||
func(array, function(value, key) {
|
var keys = [];
|
||||||
keys.push(key);
|
func(array, function(value, key) {
|
||||||
return isEvery;
|
keys.push(key);
|
||||||
});
|
return isEvery;
|
||||||
|
});
|
||||||
|
|
||||||
ok(!_.includes(keys, 'a'));
|
ok(!_.includes(keys, 'a'));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
skipTest();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
_.each(_.difference(methods, unwrappedMethods), function(methodName) {
|
_.each(_.difference(methods, unwrappedMethods), function(methodName) {
|
||||||
var array = [1, 2, 3],
|
var array = [1, 2, 3],
|
||||||
func = _[methodName];
|
func = _[methodName],
|
||||||
|
isBaseEach = methodName == '_baseEach';
|
||||||
|
|
||||||
test('`_.' + methodName + '` should return a wrapped value when chaining', 1, function() {
|
test('`_.' + methodName + '` should return a wrapped value when chaining', 1, function() {
|
||||||
if (!isNpm) {
|
if (!(isBaseEach || isNpm)) {
|
||||||
var wrapped = _(array)[methodName](_.noop);
|
var wrapped = _(array)[methodName](_.noop);
|
||||||
ok(wrapped instanceof _);
|
ok(wrapped instanceof _);
|
||||||
}
|
}
|
||||||
@@ -5154,24 +5204,35 @@
|
|||||||
function Foo() { this.a = 1; }
|
function Foo() { this.a = 1; }
|
||||||
Foo.prototype.b = 2;
|
Foo.prototype.b = 2;
|
||||||
|
|
||||||
var keys = [];
|
if (func) {
|
||||||
func(new Foo, function(value, key) { keys.push(key); });
|
var keys = [];
|
||||||
deepEqual(keys, ['a']);
|
func(new Foo, function(value, key) { keys.push(key); });
|
||||||
|
deepEqual(keys, ['a']);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
skipTest();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
_.each(iterationMethods, function(methodName) {
|
_.each(iterationMethods, function(methodName) {
|
||||||
var array = [1, 2, 3],
|
var array = [1, 2, 3],
|
||||||
func = _[methodName],
|
func = _[methodName],
|
||||||
isEach = !_.includes(objectMethods, methodName),
|
isBaseEach = methodName == '_baseEach',
|
||||||
|
isObject = _.includes(objectMethods, methodName),
|
||||||
isRight = _.includes(rightMethods, methodName);
|
isRight = _.includes(rightMethods, methodName);
|
||||||
|
|
||||||
test('`_.' + methodName + '` should return the collection', 1, function() {
|
test('`_.' + methodName + '` should return the collection', 1, function() {
|
||||||
strictEqual(func(array, Boolean), array);
|
if (func) {
|
||||||
|
strictEqual(func(array, Boolean), array);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
skipTest();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('`_.' + methodName + '` should not return the existing wrapped value when chaining', 1, function() {
|
test('`_.' + methodName + '` should not return the existing wrapped value when chaining', 1, function() {
|
||||||
if (!isNpm) {
|
if (!(isBaseEach || isNpm)) {
|
||||||
var wrapped = _(array);
|
var wrapped = _(array);
|
||||||
notStrictEqual(wrapped[methodName](_.noop), wrapped);
|
notStrictEqual(wrapped[methodName](_.noop), wrapped);
|
||||||
}
|
}
|
||||||
@@ -5186,29 +5247,34 @@
|
|||||||
},
|
},
|
||||||
function(collection, key) {
|
function(collection, key) {
|
||||||
test('`_.' + methodName + '` should work with a string ' + key + ' for `collection` (test in IE < 9)', 6, function() {
|
test('`_.' + methodName + '` should work with a string ' + key + ' for `collection` (test in IE < 9)', 6, function() {
|
||||||
var args,
|
if (func) {
|
||||||
values = [],
|
var args,
|
||||||
expectedChars = ['a', 'b', 'c'];
|
values = [],
|
||||||
|
expectedChars = ['a', 'b', 'c'];
|
||||||
|
|
||||||
var expectedArgs = isEach
|
var expectedArgs = isObject
|
||||||
? (isRight ? ['c', 2, collection] : ['a', 0, collection])
|
? (isRight ? ['c', '2', collection] : ['a', '0', collection])
|
||||||
: (isRight ? ['c', '2', collection] : ['a', '0', collection])
|
: (isRight ? ['c', 2, collection] : ['a', 0, collection]);
|
||||||
|
|
||||||
var actual = func(collection, function(value) {
|
var actual = func(collection, function(value) {
|
||||||
args || (args = slice.call(arguments));
|
args || (args = slice.call(arguments));
|
||||||
values.push(value);
|
values.push(value);
|
||||||
});
|
});
|
||||||
|
|
||||||
var stringObject = args[2];
|
var stringObject = args[2];
|
||||||
|
|
||||||
ok(_.isString(stringObject));
|
ok(_.isString(stringObject));
|
||||||
ok(_.isObject(stringObject));
|
ok(_.isObject(stringObject));
|
||||||
|
|
||||||
deepEqual([stringObject[0], stringObject[1], stringObject[2]], expectedChars);
|
deepEqual([stringObject[0], stringObject[1], stringObject[2]], expectedChars);
|
||||||
deepEqual(args, expectedArgs);
|
deepEqual(args, expectedArgs);
|
||||||
deepEqual(values, isRight ? ['c', 'b', 'a'] : expectedChars);
|
deepEqual(values, isRight ? ['c', 'b', 'a'] : expectedChars);
|
||||||
|
|
||||||
strictEqual(actual, collection);
|
strictEqual(actual, collection);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
skipTest(6);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -5217,37 +5283,74 @@
|
|||||||
var func = _[methodName];
|
var func = _[methodName];
|
||||||
|
|
||||||
test('`_.' + methodName + '` should use `isLength` to determine whether a value is array-like', 2, function() {
|
test('`_.' + methodName + '` should use `isLength` to determine whether a value is array-like', 2, function() {
|
||||||
function isIteratedAsObject(length) {
|
if (func) {
|
||||||
var result = false;
|
var isIteratedAsObject = function(length) {
|
||||||
func({ 'length': length }, function() { result = true; }, 0);
|
var result = false;
|
||||||
return result;
|
func({ 'length': length }, function() { result = true; }, 0);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
var values = [-1, '1', 1.1, Object(1), MAX_SAFE_INTEGER + 1],
|
||||||
|
expected = _.map(values, _.constant(true)),
|
||||||
|
actual = _.map(values, isIteratedAsObject);
|
||||||
|
|
||||||
|
deepEqual(actual, expected);
|
||||||
|
ok(!isIteratedAsObject(0));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
skipTest(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
var values = [-1, '1', 1.1, Object(1), MAX_SAFE_INTEGER + 1],
|
|
||||||
expected = _.map(values, _.constant(true)),
|
|
||||||
actual = _.map(values, isIteratedAsObject);
|
|
||||||
|
|
||||||
deepEqual(actual, expected);
|
|
||||||
ok(!isIteratedAsObject(0));
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
_.each(collectionMethods.concat(objectMethods), function(methodName) {
|
_.each(methods, function(methodName) {
|
||||||
var func = _[methodName];
|
var array = [1, 2, 3],
|
||||||
|
func = _[methodName],
|
||||||
|
isFind = /^find/.test(methodName),
|
||||||
|
isSome = methodName == 'some';
|
||||||
|
|
||||||
test('`_.' + methodName + '` should compute length before iteration', 2, function() {
|
test('`_.' + methodName + '` should ignore changes to `array.length`', 1, function() {
|
||||||
_.each([[0], { 'a': 0 }], function(collection) {
|
if (func) {
|
||||||
var count = 0;
|
var count = 0,
|
||||||
|
array = [1];
|
||||||
|
|
||||||
func(collection, function() {
|
func(array, function() {
|
||||||
collection[++count] = count;
|
if (++count == 1) {
|
||||||
if (count > 1) {
|
array.push(2);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}, 0);
|
return !(isFind || isSome);
|
||||||
|
}, array);
|
||||||
|
|
||||||
strictEqual(count, 1);
|
strictEqual(count, 1);
|
||||||
});
|
}
|
||||||
|
else {
|
||||||
|
skipTest();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
_.each(_.difference(_.union(methods, collectionMethods), arrayMethods), function(methodName) {
|
||||||
|
var func = _[methodName],
|
||||||
|
isFind = /^find/.test(methodName),
|
||||||
|
isSome = methodName == 'some';
|
||||||
|
|
||||||
|
test('`_.' + methodName + '` should ignore added `object` properties', 1, function() {
|
||||||
|
if (func) {
|
||||||
|
var count = 0,
|
||||||
|
object = { 'a': 1 };
|
||||||
|
|
||||||
|
func(object, function() {
|
||||||
|
if (++count == 1) {
|
||||||
|
object.b = 2;
|
||||||
|
}
|
||||||
|
return !(isFind || isSome);
|
||||||
|
}, object);
|
||||||
|
|
||||||
|
strictEqual(count, 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
skipTest();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}());
|
}());
|
||||||
@@ -5474,31 +5577,39 @@
|
|||||||
|
|
||||||
_.each(['_baseEach', 'forEach', 'forEachRight', 'forIn', 'forInRight', 'forOwn', 'forOwnRight', 'transform'], function(methodName) {
|
_.each(['_baseEach', 'forEach', 'forEachRight', 'forIn', 'forInRight', 'forOwn', 'forOwnRight', 'transform'], function(methodName) {
|
||||||
var func = _[methodName];
|
var func = _[methodName];
|
||||||
if (!func) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
test('`_.' + methodName + '` can exit early when iterating arrays', 1, function() {
|
test('`_.' + methodName + '` can exit early when iterating arrays', 1, function() {
|
||||||
var array = [1, 2, 3],
|
if (func) {
|
||||||
values = [];
|
var array = [1, 2, 3],
|
||||||
|
values = [];
|
||||||
|
|
||||||
func(array, function(value, other) {
|
func(array, function(value, other) {
|
||||||
values.push(_.isArray(value) ? other : value);
|
values.push(_.isArray(value) ? other : value);
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
deepEqual(values, [_.endsWith(methodName, 'Right') ? 3 : 1]);
|
deepEqual(values, [_.endsWith(methodName, 'Right') ? 3 : 1]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
skipTest();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('`_.' + methodName + '` can exit early when iterating objects', 1, function() {
|
test('`_.' + methodName + '` can exit early when iterating objects', 1, function() {
|
||||||
var object = { 'a': 1, 'b': 2, 'c': 3 },
|
if (func) {
|
||||||
values = [];
|
var object = { 'a': 1, 'b': 2, 'c': 3 },
|
||||||
|
values = [];
|
||||||
|
|
||||||
func(object, function(value, other) {
|
func(object, function(value, other) {
|
||||||
values.push(_.isArray(value) ? other : value);
|
values.push(_.isArray(value) ? other : value);
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
strictEqual(values.length, 1);
|
strictEqual(values.length, 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
skipTest();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user