Add unit tests for createBound and _.createCallback additions.

Former-commit-id: 68ad27523352a7e7b70f026588342fb70318454b
This commit is contained in:
John-David Dalton
2013-07-21 23:44:38 -07:00
parent afeeadd665
commit b4b9910203

View File

@@ -9,6 +9,7 @@
create = Object.create, create = Object.create,
freeze = Object.freeze, freeze = Object.freeze,
process = window.process, process = window.process,
push = Array.prototype.push,
slice = Array.prototype.slice, slice = Array.prototype.slice,
system = window.system, system = window.system,
toString = Object.prototype.toString, toString = Object.prototype.toString,
@@ -72,8 +73,8 @@
var setDescriptor = (function() { var setDescriptor = (function() {
try { try {
var o = {}, var o = {},
fn = Object.defineProperty, func = Object.defineProperty,
result = fn(o, o, o) && fn; result = func(o, o, o) && func;
} catch(e) { } } catch(e) { }
return result; return result;
}()); }());
@@ -506,7 +507,7 @@
var func = _[methodName], var func = _[methodName],
klass = new Klass; klass = new Klass;
test('_.' + methodName + ' should pass the correct `callback` arguments', function() { test('`_.' + methodName + '` should pass the correct `callback` arguments', function() {
var args; var args;
func(klass, function() { func(klass, function() {
@@ -516,7 +517,7 @@
deepEqual(args, [klass]); deepEqual(args, [klass]);
}); });
test('_.' + methodName + ' should correct set the `this` binding', function() { test('`_.' + methodName + '` should correct set the `this` binding', function() {
var actual = func('a', function(value) { var actual = func('a', function(value) {
return this[value]; return this[value];
}, { 'a': 'A' }); }, { 'a': 'A' });
@@ -524,7 +525,7 @@
equal(actual, 'A'); equal(actual, 'A');
}); });
test('_.' + methodName + ' should handle cloning if `callback` returns `undefined`', function() { test('`_.' + methodName + '` should handle cloning if `callback` returns `undefined`', function() {
var actual = _.clone({ 'a': { 'b': 'c' } }, function() { }); var actual = _.clone({ 'a': { 'b': 'c' } }, function() { });
deepEqual(actual, { 'a': { 'b': 'c' } }); deepEqual(actual, { 'a': { 'b': 'c' } });
}); });
@@ -592,6 +593,28 @@
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.createCallback');
(function() {
test('should work with functions created by `_.partial` and `_.partialRight`', function() {
function func() {
var result = [this.x];
push.apply(result, arguments);
return result;
}
var expected = [1, 2, 3],
object = { 'x': 1 },
callback = _.createCallback(_.partial(func, 2), object);
deepEqual(callback(3), expected);
callback = _.createCallback(_.partialRight(func, 3), object);
deepEqual(callback(2), expected);
});
}());
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.debounce'); QUnit.module('lodash.debounce');
(function() { (function() {
@@ -807,14 +830,14 @@
_.each(['assign', 'defaults', 'merge'], function(methodName) { _.each(['assign', 'defaults', 'merge'], function(methodName) {
var func = _[methodName]; var func = _[methodName];
test('lodash.' + methodName + ' should not assign inherited `source` properties', function() { test('`_.' + methodName + '` should not assign inherited `source` properties', function() {
function Foo() {} function Foo() {}
Foo.prototype = { 'a': 1 }; Foo.prototype = { 'a': 1 };
deepEqual(func({}, new Foo), {}); deepEqual(func({}, new Foo), {});
}); });
if (methodName == 'merge') { if (methodName == 'merge') {
test('lodash.' + methodName + ' should treat sparse arrays as dense', function() { test('`_.' + methodName + '` should treat sparse arrays as dense', function() {
var array = Array(3); var array = Array(3);
array[0] = 1; array[0] = 1;
array[2] = 3; array[2] = 3;
@@ -837,7 +860,7 @@
_.each(['assign', 'bindAll', 'defaults'], function(methodName) { _.each(['assign', 'bindAll', 'defaults'], function(methodName) {
var func = _[methodName]; var func = _[methodName];
test('lodash.' + methodName + ' should not throw strict mode errors', function() { test('`_.' + methodName + '` should not throw strict mode errors', function() {
var object = { 'a': null, 'b': function(){} }, var object = { 'a': null, 'b': function(){} },
pass = true; pass = true;
@@ -1162,13 +1185,13 @@
_.each(['forEach', 'forIn', 'forOwn'], function(methodName) { _.each(['forEach', 'forIn', 'forOwn'], function(methodName) {
var func = _[methodName]; var func = _[methodName];
test('lodash.' + methodName + ' fixes the JScript [[DontEnum]] bug (test in IE < 9)', function() { test('`_.' + methodName + '` fixes the JScript [[DontEnum]] bug (test in IE < 9)', function() {
var keys = []; var keys = [];
func(shadowedObject, function(value, key) { keys.push(key); }); func(shadowedObject, function(value, key) { keys.push(key); });
deepEqual(keys.sort(), shadowedProps); deepEqual(keys.sort(), shadowedProps);
}); });
test('lodash.' + methodName + ' does not iterate over non-enumerable properties (test in IE < 9)', function() { test('`_.' + methodName + '` does not iterate over non-enumerable properties (test in IE < 9)', function() {
_.forOwn({ _.forOwn({
'Array': Array.prototype, 'Array': Array.prototype,
'Boolean': Boolean.prototype, 'Boolean': Boolean.prototype,
@@ -1199,7 +1222,7 @@
}); });
}); });
test('lodash.' + methodName + ' skips the prototype property of functions (test in Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1)', function() { test('`_.' + methodName + '` skips the prototype property of functions (test in Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1)', function() {
function Foo() {} function Foo() {}
Foo.prototype.a = 1; Foo.prototype.a = 1;
@@ -1229,7 +1252,7 @@
}); });
test('lodash.' + methodName + ' should assign problem JScript properties (test in IE < 9)', function() { test('`_.' + methodName + '` should assign problem JScript properties (test in IE < 9)', function() {
var object = { var object = {
'constructor': '0', 'constructor': '0',
'hasOwnProperty': '1', 'hasOwnProperty': '1',
@@ -1250,7 +1273,7 @@
deepEqual(func(object, source), shadowedObject); deepEqual(func(object, source), shadowedObject);
}); });
test('lodash.' + methodName + ' skips the prototype property of functions (test in Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1)', function() { test('`_.' + methodName + '` skips the prototype property of functions (test in Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1)', function() {
function Foo() {} function Foo() {}
Foo.prototype.c = 3; Foo.prototype.c = 3;
@@ -1264,7 +1287,7 @@
deepEqual(func({}, Foo), expected); deepEqual(func({}, Foo), expected);
}); });
test('lodash.' + methodName + ' should work with `_.reduce`', function() { test('`_.' + methodName + '` should work with `_.reduce`', function() {
var actual = { 'a': 1}, var actual = { 'a': 1},
array = [{ 'b': 2 }, { 'c': 3 }]; array = [{ 'b': 2 }, { 'c': 3 }];
@@ -1276,7 +1299,7 @@
_.each(['assign', 'merge'], function(methodName) { _.each(['assign', 'merge'], function(methodName) {
var func = _[methodName]; var func = _[methodName];
test('lodash.' + methodName + ' should pass the correct `callback` arguments', function() { test('`_.' + methodName + '` should pass the correct `callback` arguments', function() {
var args; var args;
func({ 'a': 1 }, { 'a': 2 }, function() { func({ 'a': 1 }, { 'a': 2 }, function() {
args || (args = slice.call(arguments)); args || (args = slice.call(arguments));
@@ -1295,7 +1318,7 @@
deepEqual(args, [array, object], 'non-primitive property values'); deepEqual(args, [array, object], 'non-primitive property values');
}); });
test('lodash.' + methodName + ' should correct set the `this` binding', function() { test('`_.' + methodName + '` should correct set the `this` binding', function() {
var actual = func({}, { 'a': 0 }, function(a, b) { var actual = func({}, { 'a': 0 }, function(a, b) {
return this[b]; return this[b];
}, [2]); }, [2]);
@@ -1303,7 +1326,7 @@
deepEqual(actual, { 'a': 2 }); deepEqual(actual, { 'a': 2 });
}); });
test('lodash.' + methodName + ' should not treat the second argument as a `callback`', function() { test('`_.' + methodName + '` should not treat the second argument as a `callback`', function() {
function callback() {} function callback() {}
callback.b = 2; callback.b = 2;
@@ -1322,7 +1345,7 @@
_.each(['forEach', 'forIn', 'forOwn'], function(methodName) { _.each(['forEach', 'forIn', 'forOwn'], function(methodName) {
var func = _[methodName]; var func = _[methodName];
test('lodash.' + methodName + ' can exit early when iterating arrays', function() { test('`_.' + methodName + '` can exit early when iterating arrays', function() {
var array = [1, 2, 3], var array = [1, 2, 3],
values = []; values = [];
@@ -1330,7 +1353,7 @@
deepEqual(values, [1]); deepEqual(values, [1]);
}); });
test('lodash.' + methodName + ' can exit early when iterating objects', function() { test('`_.' + methodName + '` can exit early when iterating objects', function() {
var object = { 'a': 1, 'b': 2, 'c': 3 }, var object = { 'a': 1, 'b': 2, 'c': 3 },
values = []; values = [];
@@ -1484,31 +1507,31 @@
var array = [1, new Foo, 3, new Foo], var array = [1, new Foo, 3, new Foo],
indexOf = _.indexOf; indexOf = _.indexOf;
test('_.contains should work with a custom `_.indexOf` method', function() { test('`_.contains` should work with a custom `_.indexOf` method', function() {
_.indexOf = custom; _.indexOf = custom;
ok(_.contains(array, new Foo)); ok(_.contains(array, new Foo));
_.indexOf = indexOf; _.indexOf = indexOf;
}); });
test('_.difference should work with a custom `_.indexOf` method', function() { test('`_.difference` should work with a custom `_.indexOf` method', function() {
_.indexOf = custom; _.indexOf = custom;
deepEqual(_.difference(array, [new Foo]), [1, 3]); deepEqual(_.difference(array, [new Foo]), [1, 3]);
_.indexOf = indexOf; _.indexOf = indexOf;
}); });
test('_.intersection should work with a custom `_.indexOf` method', function() { test('`_.intersection` should work with a custom `_.indexOf` method', function() {
_.indexOf = custom; _.indexOf = custom;
deepEqual(_.intersection(array, [new Foo]), [array[1]]); deepEqual(_.intersection(array, [new Foo]), [array[1]]);
_.indexOf = indexOf; _.indexOf = indexOf;
}); });
test('_.omit should work with a custom `_.indexOf` method', function() { test('`_.omit` should work with a custom `_.indexOf` method', function() {
_.indexOf = custom; _.indexOf = custom;
deepEqual(_.omit(array, ['x']), { '0': 1, '2': 3 }); deepEqual(_.omit(array, ['x']), { '0': 1, '2': 3 });
_.indexOf = indexOf; _.indexOf = indexOf;
}); });
test('_.uniq should work with a custom `_.indexOf` method', function() { test('`_.uniq` should work with a custom `_.indexOf` method', function() {
_.indexOf = custom; _.indexOf = custom;
deepEqual(_.uniq(array), array.slice(0, 3)); deepEqual(_.uniq(array), array.slice(0, 3));
@@ -1643,7 +1666,7 @@
}); });
test('should work with jQuery/MooTools DOM query collections', function() { test('should work with jQuery/MooTools DOM query collections', function() {
function Foo(elements) { Array.prototype.push.apply(this, elements); } function Foo(elements) { push.apply(this, elements); }
Foo.prototype = { 'length': 0, 'splice': Array.prototype.splice }; Foo.prototype = { 'length': 0, 'splice': Array.prototype.splice };
strictEqual(_.isEmpty(new Foo([])), true); strictEqual(_.isEmpty(new Foo([])), true);
@@ -1861,7 +1884,7 @@
function(methodName) { function(methodName) {
var func = _[methodName]; var func = _[methodName];
test('lodash.' + methodName + ' should return a boolean', function() { test('`_.' + methodName + '` should return a boolean', function() {
var expected = 'boolean'; var expected = 'boolean';
equal(typeof func(arguments), expected); equal(typeof func(arguments), expected);
@@ -1890,7 +1913,7 @@
var object = new Foo; var object = new Foo;
if (toString.call(object) == '[object Object]') { if (toString.call(object) == '[object Object]') {
strictEqual(_[methodName](object), false, '_.' + methodName + ' returns `false`'); strictEqual(_[methodName](object), false, '`_.' + methodName + '` returns `false`');
} else { } else {
skipTest(); skipTest();
} }
@@ -2074,7 +2097,7 @@
_.each(['max', 'min'], function(methodName) { _.each(['max', 'min'], function(methodName) {
var func = _[methodName]; var func = _[methodName];
test('lodash.' + methodName + ' should iterate an object', function() { test('`_.' + methodName + '` should iterate an object', function() {
var actual = func({ 'a': 1, 'b': 2, 'c': 3 }); var actual = func({ 'a': 1, 'b': 2, 'c': 3 });
equal(actual, methodName == 'max' ? 3 : 1); equal(actual, methodName == 'max' ? 3 : 1);
}); });
@@ -2087,7 +2110,7 @@
_.each(['max', 'min'], function(methodName) { _.each(['max', 'min'], function(methodName) {
var func = _[methodName]; var func = _[methodName];
test('lodash.' + methodName + ' should iterate a string', function() { test('`_.' + methodName + '` should iterate a string', function() {
_.each(['abc', Object('abc')], function(value) { _.each(['abc', Object('abc')], function(value) {
var actual = func(value); var actual = func(value);
equal(actual, methodName == 'max' ? 'c' : 'a'); equal(actual, methodName == 'max' ? 'c' : 'a');
@@ -2100,7 +2123,7 @@
QUnit.module('lodash.max and lodash.min chaining'); QUnit.module('lodash.max and lodash.min chaining');
_.each(['max', 'min'], function(methodName) { _.each(['max', 'min'], function(methodName) {
test('lodash.' + methodName + ' should resolve the correct value when passed an array containing only one value', function() { test('`_.' + methodName + '` should resolve the correct value when passed an array containing only one value', function() {
var actual = _([40])[methodName]().value(); var actual = _([40])[methodName]().value();
strictEqual(actual, 40); strictEqual(actual, 40);
}); });
@@ -2384,14 +2407,14 @@
_.each(['partial', 'partialRight'], function(methodName) { _.each(['partial', 'partialRight'], function(methodName) {
var func = _[methodName]; var func = _[methodName];
test('lodash.' + methodName + ' partially applies an argument, without additional arguments', function() { test('`_.' + methodName + '` partially applies an argument, without additional arguments', function() {
var arg = 'a', var arg = 'a',
fn = function(x) { return x; }; fn = function(x) { return x; };
equal(func(fn, arg)(), arg); equal(func(fn, arg)(), arg);
}); });
test('lodash.' + methodName + ' partially applies an argument, with additional arguments', function() { test('`_.' + methodName + '` partially applies an argument, with additional arguments', function() {
var arg1 = 'a', var arg1 = 'a',
arg2 = 'b', arg2 = 'b',
expected = [arg1, arg2], expected = [arg1, arg2],
@@ -2403,19 +2426,19 @@
deepEqual(func(fn, arg1)(arg2), expected); deepEqual(func(fn, arg1)(arg2), expected);
}); });
test('lodash.' + methodName + ' works without partially applying arguments, without additional arguments', function() { test('`_.' + methodName + '` works without partially applying arguments, without additional arguments', function() {
var fn = function() { return arguments.length; }; var fn = function() { return arguments.length; };
strictEqual(func(fn)(), 0); strictEqual(func(fn)(), 0);
}); });
test('lodash.' + methodName + ' works without partially applying arguments, with additional arguments', function() { test('`_.' + methodName + '` works without partially applying arguments, with additional arguments', function() {
var arg = 'a', var arg = 'a',
fn = function(x) { return x; }; fn = function(x) { return x; };
equal(func(fn)(arg), arg); equal(func(fn)(arg), arg);
}); });
test('lodash.' + methodName + ' should not alter the `this` binding of either function', function() { test('`_.' + methodName + '` should not alter the `this` binding of either function', function() {
var object = { 'a': 1 }, var object = { 'a': 1 },
fn = function() { return this.a; }; fn = function() { return this.a; };
@@ -2441,6 +2464,62 @@
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('methods using `createBound`');
(function() {
test('combinations of partial functions should work', function() {
function func() {
return slice.call(arguments);
}
var a = _.partial(func),
b = _.partialRight(a, 3),
c = _.partial(b, 1);
deepEqual(c(2), [1, 2, 3]);
});
test('combinations of bound and partial functions should work', function() {
function func() {
var result = [this.x];
push.apply(result, arguments);
return result;
}
var expected = [1, 2, 3, 4],
object = { 'func': func, 'x': 1 };
var a = _.bindKey(object, 'func'),
b = _.partialRight(a, 4),
c = _.partial(b, 2);
deepEqual(c(3), expected);
a = _.bind(func, object);
b = _.partialRight(a, 4);
c = _.partial(b, 2);
deepEqual(c(3), expected);
a = _.partial(func, 2);
b = _.bind(a, object);
c = _.partialRight(b, 4);
deepEqual(c(3), expected);
});
test('recursively bound functions should work', function() {
function func() {
return this.x;
}
var a = _.bind(func, { 'x': 1 }),
b = _.bind(a, { 'x': 2 }),
c = _.bind(b, { 'x': 3 });
strictEqual(c(), 1);
});
}());
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.pick'); QUnit.module('lodash.pick');
(function() { (function() {
@@ -2791,7 +2870,7 @@
}); });
test('should work with jQuery/MooTools DOM query collections', function() { test('should work with jQuery/MooTools DOM query collections', function() {
function Foo(elements) { Array.prototype.push.apply(this, elements); } function Foo(elements) { push.apply(this, elements); }
Foo.prototype = { 'length': 0, 'splice': Array.prototype.splice }; Foo.prototype = { 'length': 0, 'splice': Array.prototype.splice };
equal(_.size(new Foo([1, 2, 3])), 3); equal(_.size(new Foo([1, 2, 3])), 3);
@@ -3421,7 +3500,7 @@
count = Math.ceil(largeArraySize / expected.length); count = Math.ceil(largeArraySize / expected.length);
_.times(count, function() { _.times(count, function() {
array.push.apply(array, expected); push.apply(array, expected);
}); });
deepEqual(_.uniq(array), expected); deepEqual(_.uniq(array), expected);
@@ -3649,7 +3728,7 @@
]; ];
_.each(funcs, function(methodName) { _.each(funcs, function(methodName) {
test('_.' + methodName + ' should return a wrapped value', function() { test('`_.' + methodName + '` should return a wrapped value', function() {
ok(wrapped[methodName]() instanceof _); ok(wrapped[methodName]() instanceof _);
}); });
}); });
@@ -3697,7 +3776,7 @@
]; ];
_.each(funcs, function(methodName) { _.each(funcs, function(methodName) {
test('_.' + methodName + ' should return an unwrapped value', function() { test('`_.' + methodName + '` should return an unwrapped value', function() {
var result = methodName == 'reduceRight' var result = methodName == 'reduceRight'
? wrapped[methodName](_.identity) ? wrapped[methodName](_.identity)
: wrapped[methodName](); : wrapped[methodName]();
@@ -3721,11 +3800,11 @@
]; ];
_.each(funcs, function(methodName) { _.each(funcs, function(methodName) {
test('_.' + methodName + ' should return an unwrapped value', function() { test('`_.' + methodName + '` should return an unwrapped value', function() {
equal(typeof wrapped[methodName](), 'number'); equal(typeof wrapped[methodName](), 'number');
}); });
test('_.' + methodName + ' should return a wrapped value', function() { test('`_.' + methodName + '` should return a wrapped value', function() {
ok(wrapped[methodName](1) instanceof _); ok(wrapped[methodName](1) instanceof _);
}); });
}); });
@@ -3741,7 +3820,7 @@
test('should work with `arguments` objects', function() { test('should work with `arguments` objects', function() {
function message(methodName) { function message(methodName) {
return '_.' + methodName + ' should work with `arguments` objects'; return '`_.' + methodName + '` should work with `arguments` objects';
} }
deepEqual(_.at(args, 0, 4), [1, 5], message('at')); deepEqual(_.at(args, 0, 4), [1, 5], message('at'));
@@ -3771,7 +3850,7 @@
test('should allow falsey primary arguments', function() { test('should allow falsey primary arguments', function() {
function message(methodName) { function message(methodName) {
return '_.' + methodName + ' should allow falsey primary arguments'; return '`_.' + methodName + '` should allow falsey primary arguments';
} }
deepEqual(_.difference(null, array), [], message('difference')); deepEqual(_.difference(null, array), [], message('difference'));
@@ -3781,7 +3860,7 @@
test('should allow falsey secondary arguments', function() { test('should allow falsey secondary arguments', function() {
function message(methodName) { function message(methodName) {
return '_.' + methodName + ' should allow falsey secondary arguments'; return '`_.' + methodName + '` should allow falsey secondary arguments';
} }
deepEqual(_.difference(array, null), array, message('difference')); deepEqual(_.difference(array, null), array, message('difference'));
@@ -3875,7 +3954,7 @@
if (_.indexOf(returnArrays, methodName) > -1) { if (_.indexOf(returnArrays, methodName) > -1) {
deepEqual(actual, expected, '_.' + methodName + ' returns an array'); deepEqual(actual, expected, '_.' + methodName + ' returns an array');
} }
ok(pass, '_.' + methodName + ' allows falsey arguments'); ok(pass, '`_.' + methodName + '` allows falsey arguments');
}); });
}); });
@@ -3911,7 +3990,7 @@
_.each(funcs, function(methodName) { _.each(funcs, function(methodName) {
var func = _[methodName], var func = _[methodName],
message = '_.' + methodName + ' handles `null` `thisArg` arguments'; message = '`_.' + methodName + '` handles `null` `thisArg` arguments';
thisArg = undefined; thisArg = undefined;