"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "test/test.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.

test.js  (lodash-3.0.0):test.js  (lodash-4.0.0)
skipping to change at line 15 skipping to change at line 15
/** Used to detect when a function becomes hot. */ /** Used to detect when a function becomes hot. */
var HOT_COUNT = 150; var HOT_COUNT = 150;
/** Used as the size to cover large array optimizations. */ /** Used as the size to cover large array optimizations. */
var LARGE_ARRAY_SIZE = 200; var LARGE_ARRAY_SIZE = 200;
/** Used as the `TypeError` message for "Functions" methods. */ /** Used as the `TypeError` message for "Functions" methods. */
var FUNC_ERROR_TEXT = 'Expected a function'; var FUNC_ERROR_TEXT = 'Expected a function';
/** Used as references for the max length and index of an array. */ /** Used as references for various `Number` constants. */
var MAX_ARRAY_LENGTH = Math.pow(2, 32) - 1, var MAX_SAFE_INTEGER = 9007199254740991,
MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1; MAX_INTEGER = 1.7976931348623157e+308;
/** Used as the maximum length an array-like object. */ /** Used as references for the maximum length and index of an array. */
var MAX_SAFE_INTEGER = Math.pow(2, 53) - 1; var MAX_ARRAY_LENGTH = 4294967295,
MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1;
/** `Object#toString` result references. */ /** `Object#toString` result references. */
var funcTag = '[object Function]', var funcTag = '[object Function]',
numberTag = '[object Number]', numberTag = '[object Number]',
objectTag = '[object Object]'; objectTag = '[object Object]';
/** Used as a reference to the global object. */ /** Used as a reference to the global object. */
var root = (typeof global == 'object' && global) || this; var root = (typeof global == 'object' && global) || this;
/** Used to store lodash to test for bad extensions/shims. */ /** Used to store lodash to test for bad extensions/shims. */
var lodashBizarro = root.lodashBizarro; var lodashBizarro = root.lodashBizarro;
/** Used for native method references. */ /** Used for native method references. */
var arrayProto = Array.prototype, var arrayProto = Array.prototype,
errorProto = Error.prototype, errorProto = Error.prototype,
funcProto = Function.prototype, funcProto = Function.prototype,
objectProto = Object.prototype, objectProto = Object.prototype,
numberProto = Number.prototype,
stringProto = String.prototype; stringProto = String.prototype;
/** Method and object shortcuts. */ /** Method and object shortcuts. */
var phantom = root.phantom, var phantom = root.phantom,
amd = root.define && define.amd, amd = root.define && define.amd,
argv = root.process && process.argv, argv = root.process && process.argv,
ArrayBuffer = root.ArrayBuffer, ArrayBuffer = root.ArrayBuffer,
defineProperty = Object.defineProperty,
document = !phantom && root.document, document = !phantom && root.document,
body = root.document && root.document.body, body = root.document && root.document.body,
create = Object.create, create = Object.create,
fnToString = funcProto.toString, fnToString = funcProto.toString,
freeze = Object.freeze, freeze = Object.freeze,
hasOwnProperty = objectProto.hasOwnProperty, identity = function(value) { return value; },
JSON = root.JSON, JSON = root.JSON,
Map = root.Map,
noop = function() {}, noop = function() {},
objToString = objectProto.toString, objToString = objectProto.toString,
params = root.arguments, params = argv,
push = arrayProto.push, push = arrayProto.push,
realm = {},
Set = root.Set,
slice = arrayProto.slice, slice = arrayProto.slice,
system = root.system, Symbol = root.Symbol,
Uint8Array = root.Uint8Array; symbol = Symbol ? Symbol('a') : undefined,
Uint8Array = root.Uint8Array,
/** Used to set property descriptors. */ WeakMap = root.WeakMap;
var defineProperty = (function() {
try { /** Math helpers. */
var o = {}, var add = function(x, y) { return x + y; },
func = Object.defineProperty, doubled = function(n) { return n * 2; },
result = func(o, o, o) && func; isEven = function(n) { return n % 2 == 0; },
} catch(e) {} square = function(n) { return n * n; };
return result;
}()); /** Constant functions. */
var alwaysA = function() { return 'a'; },
alwaysB = function() { return 'b'; },
alwaysC = function() { return 'c'; };
var alwaysTrue = function() { return true; },
alwaysFalse = function() { return false; };
var alwaysNaN = function() { return NaN; },
alwaysNull = function() { return null; },
alwaysUndefined = function() { return undefined; };
var alwaysZero = function() { return 0; },
alwaysOne = function() { return 1; },
alwaysTwo = function() { return 2; },
alwaysThree = function() { return 3; },
alwaysFour = function() { return 4; };
var alwaysEmptyArray = function() { return []; },
alwaysEmptyObject = function() { return {}; },
alwaysEmptyString = function() { return ''; };
/** The file path of the lodash file to test. */ /** The file path of the lodash file to test. */
var filePath = (function() { var filePath = (function() {
var min = 0, var min = 2,
result = []; result = params || [];
if (phantom) { if (phantom) {
result = params = phantom.args; min = 0;
} else if (system) { result = params = phantom.args || require('system').args;
min = 1;
result = params = system.args;
} else if (argv) {
min = 2;
result = params = argv;
} else if (params) {
result = params;
} }
var last = result[result.length - 1]; var last = result[result.length - 1];
result = (result.length > min && !/test(?:\.js)?$/.test(last)) ? last : '../ lodash.src.js'; result = (result.length > min && !/test(?:\.js)?$/.test(last)) ? last : '../ lodash.js';
if (!amd) { if (!amd) {
try { try {
result = require('fs').realpathSync(result); result = require('fs').realpathSync(result);
} catch(e) {} } catch (e) {}
try { try {
result = require.resolve(result); result = require.resolve(result);
} catch(e) {} } catch (e) {}
} }
return result; return result;
}()); }());
/** The `ui` object. */ /** The `ui` object. */
var ui = root.ui || (root.ui = { var ui = root.ui || (root.ui = {
'buildPath': filePath, 'buildPath': filePath,
'loaderPath': '', 'loaderPath': '',
'isModularize': /\b(?:amd|commonjs|es6?|node|npm|(index|main)\.js)\b/.test(f ilePath), 'isModularize': /\b(?:amd|commonjs|es6?|node|npm|(index|main)\.js)\b/.test(f ilePath),
'isStrict': /\bes6?\b/.test(filePath), 'isStrict': /\bes6?\b/.test(filePath),
'urlParams': {} 'urlParams': {}
}); });
/** The basename of the lodash file to test. */ /** The basename of the lodash file to test. */
var basename = /[\w.-]+$/.exec(filePath)[0]; var basename = /[\w.-]+$/.exec(filePath)[0];
/** Detect if in a Java environment. */
var isJava = !document && !!root.java;
/** Used to indicate testing a modularized build. */ /** Used to indicate testing a modularized build. */
var isModularize = ui.isModularize; var isModularize = ui.isModularize;
/** Detect if testing `npm` modules. */ /** Detect if testing `npm` modules. */
var isNpm = isModularize && /\bnpm\b/.test([ui.buildPath, ui.urlParams.build]) ; var isNpm = isModularize && /\bnpm\b/.test([ui.buildPath, ui.urlParams.build]) ;
/** Detect if running in PhantomJS. */ /** Detect if running in PhantomJS. */
var isPhantom = phantom || typeof callPhantom == 'function'; var isPhantom = phantom || (typeof callPhantom == 'function');
/** Detect if running in Rhino. */
var isRhino = isJava && typeof global == 'function' && global().Array === root
.Array;
/** Detect if lodash is in strict mode. */ /** Detect if lodash is in strict mode. */
var isStrict = ui.isStrict; var isStrict = ui.isStrict;
/** Used to test Web Workers. */
var Worker = !(ui.isForeign || ui.isSauceLabs || isModularize) && document &&
root.Worker;
/** Used to test host objects in IE. */
try {
var xml = new ActiveXObject('Microsoft.XMLDOM');
} catch(e) {}
/** Use a single "load" function. */
var load = (typeof require == 'function' && !amd)
? require
: (isJava ? root.load : noop);
/** The unit testing framework. */
var QUnit = root.QUnit || (root.QUnit = (
QUnit = load('../node_modules/qunitjs/qunit/qunit.js') || root.QUnit,
QUnit = QUnit.QUnit || QUnit
));
/** Load and install QUnit Extras and ES6 Set/WeakMap shims. */
(function() {
var paths = [
'./asset/set.js',
'./asset/weakmap.js',
'../node_modules/qunit-extras/qunit-extras.js'
];
var index = -1,
length = paths.length;
while (++index < length) {
var object = load(paths[index]);
if (object) {
object.runInContext(root);
}
}
}());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
// Log params provided to `test.js`. // Leak to avoid sporadic `noglobals` fails on Edge in Sauce Labs.
if (params) { root.msWDfn = undefined;
console.log('test.js invoked with arguments: ' + JSON.stringify(slice.call(p
arams)));
}
// Exit early if going to run tests in a PhantomJS web page. // Exit early if going to run tests in a PhantomJS web page.
if (phantom && isModularize) { if (phantom && isModularize) {
var page = require('webpage').create(); var page = require('webpage').create();
page.open(filePath, function(status) {
if (status != 'success') {
console.log('PhantomJS failed to load page: ' + filePath);
phantom.exit(1);
}
});
page.onCallback = function(details) { page.onCallback = function(details) {
var coverage = details.coverage; var coverage = details.coverage;
if (coverage) { if (coverage) {
var fs = require('fs'), var fs = require('fs'),
cwd = fs.workingDirectory, cwd = fs.workingDirectory,
sep = fs.separator; sep = fs.separator;
fs.write([cwd, 'coverage', 'coverage.json'].join(sep), JSON.stringify(co verage)); fs.write([cwd, 'coverage', 'coverage.json'].join(sep), JSON.stringify(co verage));
} }
skipping to change at line 212 skipping to change at line 180
page.evaluate(function() { page.evaluate(function() {
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
QUnit.done(function(details) { QUnit.done(function(details) {
details.coverage = window.__coverage__; details.coverage = window.__coverage__;
callPhantom(details); callPhantom(details);
}); });
}); });
}); });
}; };
page.open(filePath, function(status) {
if (status != 'success') {
console.log('PhantomJS failed to load page: ' + filePath);
phantom.exit(1);
}
});
console.log('test.js invoked with arguments: ' + JSON.stringify(slice.call(p
arams)));
return; return;
} }
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
/** Used to test Web Workers. */
var Worker = !(ui.isForeign || ui.isSauceLabs || isModularize) &&
(document && document.origin != 'null') && root.Worker;
/** Used to test host objects in IE. */
try {
var xml = new ActiveXObject('Microsoft.XMLDOM');
} catch (e) {}
/** Poison the free variable `root` in Node.js */
try {
defineProperty(global.root, 'root', {
'configurable': false,
'enumerable': false,
'get': function() { throw new ReferenceError; }
});
} catch (e) {}
/** Use a single "load" function. */
var load = (!amd && typeof require == 'function')
? require
: noop;
/** The unit testing framework. */
var QUnit = root.QUnit || (root.QUnit = load('../node_modules/qunitjs/qunit/qu
nit.js'));
/** Load stable Lodash and QUnit Extras. */
var lodashStable = root.lodashStable || load('../node_modules/lodash/index.js'
);
if (lodashStable) {
lodashStable = lodashStable.runInContext(root);
}
var QUnitExtras = load('../node_modules/qunit-extras/qunit-extras.js');
if (QUnitExtras) {
QUnitExtras.runInContext(root);
}
/** The `lodash` function to test. */ /** The `lodash` function to test. */
var _ = root._ || (root._ = ( var _ = root._ || (root._ = (
_ = load(filePath) || root._, _ = load(filePath),
_ = _._ || (isStrict = ui.isStrict = isStrict || 'default' in _, _['default' ]) || _, _ = _._ || (isStrict = ui.isStrict = isStrict || 'default' in _, _['default' ]) || _,
(_.runInContext ? _.runInContext(root) : _) (_.runInContext ? _.runInContext(root) : _)
)); ));
/** Used to detect instrumented istanbul code coverage runs. */
var coverage = root.__coverage__ || root[lodashStable.findKey(root, function(v
alue, key) {
return /^(?:\$\$cov_\d+\$\$)$/.test(key);
})];
/** Used to restore the `_` reference. */
var oldDash = root._;
/** Used to test generator functions. */
var generator = lodashStable.attempt(function() {
return Function('return function*(){}');
});
/** List of latin-1 supplementary letters to basic latin letters. */ /** List of latin-1 supplementary letters to basic latin letters. */
var burredLetters = [ var burredLetters = [
'\xc0', '\xc1', '\xc2', '\xc3', '\xc4', '\xc5', '\xc6', '\xc7', '\xc8', '\xc 9', '\xca', '\xcb', '\xcc', '\xcd', '\xce', '\xc0', '\xc1', '\xc2', '\xc3', '\xc4', '\xc5', '\xc6', '\xc7', '\xc8', '\xc 9', '\xca', '\xcb', '\xcc', '\xcd', '\xce',
'\xcf', '\xd0', '\xd1', '\xd2', '\xd3', '\xd4', '\xd5', '\xd6', '\xd8', '\xd 9', '\xda', '\xdb', '\xdc', '\xdd', '\xde', '\xcf', '\xd0', '\xd1', '\xd2', '\xd3', '\xd4', '\xd5', '\xd6', '\xd8', '\xd 9', '\xda', '\xdb', '\xdc', '\xdd', '\xde',
'\xdf', '\xe0', '\xe1', '\xe2', '\xe3', '\xe4', '\xe5', '\xe6', '\xe7', '\xe 8', '\xe9', '\xea', '\xeb', '\xec', '\xed', '\xee', '\xdf', '\xe0', '\xe1', '\xe2', '\xe3', '\xe4', '\xe5', '\xe6', '\xe7', '\xe 8', '\xe9', '\xea', '\xeb', '\xec', '\xed', '\xee',
'\xef', '\xf0', '\xf1', '\xf2', '\xf3', '\xf4', '\xf5', '\xf6', '\xf8', '\xf 9', '\xfa', '\xfb', '\xfc', '\xfd', '\xfe', '\xff' '\xef', '\xf0', '\xf1', '\xf2', '\xf3', '\xf4', '\xf5', '\xf6', '\xf8', '\xf 9', '\xfa', '\xfb', '\xfc', '\xfd', '\xfe', '\xff'
]; ];
/** List of combining diacritical marks. */
var comboMarks = [
'\u0300', '\u0301', '\u0302', '\u0303', '\u0304', '\u0305', '\u0306', '\u030
7', '\u0308', '\u0309', '\u030a', '\u030b', '\u030c', '\u030d', '\u030e', '\u030
f',
'\u0310', '\u0311', '\u0312', '\u0313', '\u0314', '\u0315', '\u0316', '\u031
7', '\u0318', '\u0319', '\u031a', '\u031b', '\u031c', '\u031d', '\u031e', '\u031
f',
'\u0320', '\u0321', '\u0322', '\u0323', '\u0324', '\u0325', '\u0326', '\u032
7', '\u0328', '\u0329', '\u032a', '\u032b', '\u032c', '\u032d', '\u032e', '\u032
f',
'\u0330', '\u0331', '\u0332', '\u0333', '\u0334', '\u0335', '\u0336', '\u033
7', '\u0338', '\u0339', '\u033a', '\u033b', '\u033c', '\u033d', '\u033e', '\u033
f',
'\u0340', '\u0341', '\u0342', '\u0343', '\u0344', '\u0345', '\u0346', '\u034
7', '\u0348', '\u0349', '\u034a', '\u034b', '\u034c', '\u034d', '\u034e', '\u034
f',
'\u0350', '\u0351', '\u0352', '\u0353', '\u0354', '\u0355', '\u0356', '\u035
7', '\u0358', '\u0359', '\u035a', '\u035b', '\u035c', '\u035d', '\u035e', '\u035
f',
'\u0360', '\u0361', '\u0362', '\u0363', '\u0364', '\u0365', '\u0366', '\u036
7', '\u0368', '\u0369', '\u036a', '\u036b', '\u036c', '\u036d', '\u036e', '\u036
f',
'\ufe20', '\ufe21', '\ufe22', '\ufe23'
];
/** List of `burredLetters` translated to basic latin letters. */ /** List of `burredLetters` translated to basic latin letters. */
var deburredLetters = [ var deburredLetters = [
'A', 'A', 'A', 'A', 'A', 'A', 'Ae', 'C', 'E', 'E', 'E', 'E', 'I', 'I', 'I' , 'A', 'A', 'A', 'A', 'A', 'A', 'Ae', 'C', 'E', 'E', 'E', 'E', 'I', 'I', 'I' ,
'I', 'D', 'N', 'O', 'O', 'O', 'O', 'O', 'O', 'U', 'U', 'U', 'U', 'Y', 'Th ', 'I', 'D', 'N', 'O', 'O', 'O', 'O', 'O', 'O', 'U', 'U', 'U', 'U', 'Y', 'Th ',
'ss', 'a', 'a', 'a', 'a', 'a', 'a', 'ae', 'c', 'e', 'e', 'e', 'e', 'i', 'i' , 'i', 'ss', 'a', 'a', 'a', 'a', 'a', 'a', 'ae', 'c', 'e', 'e', 'e', 'e', 'i', 'i' , 'i',
'i', 'd', 'n', 'o', 'o', 'o', 'o', 'o', 'o', 'u', 'u', 'u', 'u', 'y', 'th ', 'y' 'i', 'd', 'n', 'o', 'o', 'o', 'o', 'o', 'o', 'u', 'u', 'u', 'u', 'y', 'th ', 'y'
]; ];
/** List of emoji modifiers. */
var emojiModifiers = [
'\ud83c\udffb',
'\ud83c\udffc',
'\ud83c\udffd',
'\ud83c\udffe',
'\ud83c\udfff'
];
/** Used to specify the emoji style glyph variant of characters. */
var emojiVar = '\ufe0f';
/** Used to provide falsey values to methods. */ /** Used to provide falsey values to methods. */
var falsey = [, '', 0, false, NaN, null, undefined]; var falsey = [, '', 0, false, NaN, null, undefined];
/** Used to provide empty values to methods. */ /** Used to provide empty values to methods. */
var empties = [[], {}].concat(falsey.slice(1)); var empties = [[], {}].concat(falsey.slice(1));
/** Used to test error objects. */ /** Used to test error objects. */
var errors = [ var errors = [
new Error, new Error,
new EvalError, new EvalError,
new RangeError, new RangeError,
new ReferenceError, new ReferenceError,
new SyntaxError, new SyntaxError,
new TypeError, new TypeError,
new URIError new URIError
]; ];
/** Used to check problem JScript properties (a.k.a. the `[[DontEnum]]` bug).
*/
var shadowProps = [
'constructor',
'hasOwnProperty',
'isPrototypeOf',
'propertyIsEnumerable',
'toLocaleString',
'toString',
'valueOf'
];
/** Used to check problem JScript properties too. */
var shadowObject = _.invert(shadowProps);
/** Used to check whether methods support typed arrays. */ /** Used to check whether methods support typed arrays. */
var typedArrays = [ var typedArrays = [
'Float32Array', 'Float32Array',
'Float64Array', 'Float64Array',
'Int8Array', 'Int8Array',
'Int16Array', 'Int16Array',
'Int32Array', 'Int32Array',
'Uint8Array', 'Uint8Array',
'Uint8ClampedArray', 'Uint8ClampedArray',
'Uint16Array', 'Uint16Array',
'Uint32Array' 'Uint32Array'
]; ];
/** /**
* Used to check for problems removing whitespace. For a whitespace reference * Used to check for problems removing whitespace. For a whitespace reference,
* see V8's unit test https://code.google.com/p/v8/source/browse/branches/blee * see [V8's unit test](https://code.google.com/p/v8/source/browse/branches/bl
ding_edge/test/mjsunit/whitespaces.js. eeding_edge/test/mjsunit/whitespaces.js).
*/ */
var whitespace = ' \t\x0b\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\ var whitespace = lodashStable.filter([
u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000'; // Basic whitespace characters.
' ', '\t', '\x0b', '\f', '\xa0', '\ufeff',
// Line terminators.
'\n', '\r', '\u2028', '\u2029',
// Unicode category "Zs" space separators.
'\u1680', '\u180e', '\u2000', '\u2001', '\u2002', '\u2003', '\u2004', '\u200
5',
'\u2006', '\u2007', '\u2008', '\u2009', '\u200a', '\u202f', '\u205f', '\u300
0'
],
function(chr) { return /\s/.exec(chr); })
.join('');
/** /**
* Extracts the unwrapped value from its wrapper. * Extracts the unwrapped value from its wrapper.
* *
* @private * @private
* @param {Object} wrapper The wrapper to unwrap. * @param {Object} wrapper The wrapper to unwrap.
* @returns {*} Returns the unwrapped value. * @returns {*} Returns the unwrapped value.
*/ */
function getUnwrappedValue(wrapper) { function getUnwrappedValue(wrapper) {
var index = -1, var index = -1,
skipping to change at line 320 skipping to change at line 367
return result; return result;
} }
/** /**
* Removes all own enumerable properties from a given object. * Removes all own enumerable properties from a given object.
* *
* @private * @private
* @param {Object} object The object to empty. * @param {Object} object The object to empty.
*/ */
function emptyObject(object) { function emptyObject(object) {
_.forOwn(object, function(value, key, object) { lodashStable.forOwn(object, function(value, key, object) {
delete object[key]; delete object[key];
}); });
} }
/** /**
* Sets a non-enumerable property value on `object`. * Sets a non-enumerable property value on `object`.
* *
* Note: This function is used to avoid a bug in older versions of V8 where * Note: This function is used to avoid a bug in older versions of V8 where
* overwriting non-enumerable built-ins makes them enumerable. * overwriting non-enumerable built-ins makes them enumerable.
* See https://code.google.com/p/v8/issues/detail?id=1623 * See https://code.google.com/p/v8/issues/detail?id=1623
* *
* @private * @private
* @param {Object} object The object augment. * @param {Object} object The object modify.
* @param {string} key The name of the property to set. * @param {string} key The name of the property to set.
* @param {*} value The property value. * @param {*} value The property value.
*/ */
function setProperty(object, key, value) { function setProperty(object, key, value) {
try { try {
defineProperty(object, key, { defineProperty(object, key, {
'configurable': true, 'configurable': true,
'enumerable': false, 'enumerable': false,
'writable': true, 'writable': true,
'value': value 'value': value
}); });
} catch(e) { } catch (e) {
object[key] = value; object[key] = value;
} }
return object;
} }
/** /**
* Skips a given number of tests with a passing result. * Skips a given number of tests with a passing result.
* *
* @private * @private
* @param {Object} assert The QUnit assert object.
* @param {number} [count=1] The number of tests to skip. * @param {number} [count=1] The number of tests to skip.
*/ */
function skipTest(count) { function skipTest(assert, count) {
count || (count = 1); count || (count = 1);
while (count--) { while (count--) {
ok(true, 'test skipped'); assert.ok(true, 'test skipped');
} }
} }
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
// Setup values for Node.js. // Add bizarro values.
(function() { (function() {
if (amd) { if (document || (typeof require != 'function')) {
return; return;
} }
try {
// Add values from a different realm.
_.extend(_, require('vm').runInNewContext([
'(function() {',
' var object = {',
" '_arguments': (function() { return arguments; }(1, 2, 3)),",
" '_array': [1, 2, 3],",
" '_boolean': Object(false),",
" '_date': new Date,",
" '_errors': [new Error, new EvalError, new RangeError, new ReferenceEr
ror, new SyntaxError, new TypeError, new URIError],",
" '_function': function() {},",
" '_nan': NaN,",
" '_null': null,",
" '_number': Object(0),",
" '_object': { 'a': 1, 'b': 2, 'c': 3 },",
" '_regexp': /x/,",
" '_string': Object('a'),",
" '_undefined': undefined",
' };',
'',
" ['" + typedArrays.join("', '") + "'].forEach(function(type) {",
" var Ctor = Function('return typeof ' + type + \" != 'undefined' &&
\" + type)()",
' if (Ctor) {',
" object['_' + type.toLowerCase()] = new Ctor(new ArrayBuffer(24));
",
' }',
" });",
'',
' return object;',
'}())'
].join('\n')));
}
catch(e) {
if (!phantom) {
return;
}
}
var nativeString = fnToString.call(toString), var nativeString = fnToString.call(toString),
reToString = /toString/g; reToString = /toString/g;
function createToString(funcName) { function createToString(funcName) {
return _.constant(nativeString.replace(reToString, funcName)); return lodashStable.constant(nativeString.replace(reToString, funcName));
} }
// Expose internal modules for better code coverage.
if (isModularize && !isNpm) {
_.each(['baseEach', 'isIndex', 'isIterateeCall', 'isLength'], function(fun
cName) {
var path = require('path'),
func = require(path.join(path.dirname(filePath), 'internal', 'baseEa
ch.js'));
_['_' + funcName] = func[funcName] || func['default'] || func;
});
}
// Allow bypassing native checks. // Allow bypassing native checks.
setProperty(funcProto, 'toString', function wrapper() { setProperty(funcProto, 'toString', function wrapper() {
setProperty(funcProto, 'toString', fnToString); setProperty(funcProto, 'toString', fnToString);
var result = _.has(this, 'toString') ? this.toString() : fnToString.call(t his); var result = _.has(this, 'toString') ? this.toString() : fnToString.call(t his);
setProperty(funcProto, 'toString', wrapper); setProperty(funcProto, 'toString', wrapper);
return result; return result;
}); });
// Add built-in prototype extensions. // Add prototype extensions.
funcProto._method = _.noop; funcProto._method = noop;
// Set bad shims. // Set bad shims.
var _isArray = Array.isArray;
setProperty(Array, 'isArray', _.noop);
var _now = Date.now;
setProperty(Date, 'now', _.noop);
var _getPrototypeOf = Object.getPrototypeOf;
setProperty(Object, 'getPrototypeOf', _.noop);
var _keys = Object.keys;
setProperty(Object, 'keys', _.noop);
var _propertyIsEnumerable = objectProto.propertyIsEnumerable; var _propertyIsEnumerable = objectProto.propertyIsEnumerable;
setProperty(objectProto, 'propertyIsEnumerable', function(key) { setProperty(objectProto, 'propertyIsEnumerable', function(key) {
if (key == '1' && _.isArguments(this) && _.isEqual(_.values(this), [0, 0]) return !(key == 'valueOf' && this && this.valueOf === 1) && _propertyIsEnu
) { merable.call(this, key);
throw new Error;
}
return _.has(this, key);
}); });
var _isFinite = Number.isFinite; if (Map) {
setProperty(Number, 'isFinite', _.noop); setProperty(root, 'Map', (function() {
var count = 0;
var _ArrayBuffer = ArrayBuffer; return function() {
setProperty(root, 'ArrayBuffer', (function() { if (count++) {
function ArrayBuffer(byteLength) { return new Map;
var buffer = new _ArrayBuffer(byteLength); }
if (!byteLength) { var result = {};
setProperty(buffer, 'slice', buffer.slice ? null : bufferSlice); setProperty(root, 'Map', Map);
} return result;
return buffer; };
}
function bufferSlice() {
var newBuffer = new _ArrayBuffer(this.byteLength),
view = new Uint8Array(newBuffer);
view.set(new Uint8Array(this));
return newBuffer;
}
setProperty(ArrayBuffer, 'toString', createToString('ArrayBuffer'));
setProperty(bufferSlice, 'toString', createToString('slice'));
return ArrayBuffer;
}()));
if (!root.Float64Array) {
setProperty(root, 'Float64Array', (function() {
function Float64Array(buffer, byteOffset, length) {
return arguments.length == 1
? new Uint8Array(buffer)
: new Uint8Array(buffer, byteOffset || 0, length || buffer.byteLengt
h);
}
setProperty(Float64Array, 'BYTES_PER_ELEMENT', 8);
setProperty(Float64Array, 'toString', createToString('Float64Array'));
return Float64Array;
}())); }()));
setProperty(root.Map, 'toString', createToString('Map'));
} }
var _parseInt = parseInt; setProperty(Object, 'create', noop);
setProperty(root, 'parseInt', (function() {
var checkStr = whitespace + '08', var _getOwnPropertySymbols = Object.getOwnPropertySymbols;
isFaked = _parseInt(checkStr) != 8, setProperty(Object, 'getOwnPropertySymbols', undefined);
reHexPrefix = /^0[xX]/,
reTrim = RegExp('^[' + whitespace + ']+|[' + whitespace + ']+$'); setProperty(root, 'Set', noop);
setProperty(root, 'Symbol', undefined);
return function(value, radix) { setProperty(root, 'WeakMap', noop);
if (value == checkStr && !isFaked) {
isFaked = true;
return 0;
}
value = String(value == null ? '' : value).replace(reTrim, '');
return _parseInt(value, +radix || (reHexPrefix.test(value) ? 16 : 10));
};
}()));
var _Set = root.Set;
setProperty(root, 'Set', _.noop);
var _WeakMap = root.WeakMap;
setProperty(root, 'WeakMap', _.noop);
// Fake the DOM.
setProperty(root, 'window', {});
setProperty(root.window, 'document', {});
setProperty(root.window.document, 'createDocumentFragment', function() {
return { 'nodeType': 11 };
});
// Fake `WinRTError`. // Fake `WinRTError`.
setProperty(root, 'WinRTError', Error); setProperty(root, 'WinRTError', Error);
// Clear cache so lodash can be reloaded. // Clear cache so lodash can be reloaded.
emptyObject(require.cache); emptyObject(require.cache);
// Load lodash and expose it to the bad extensions/shims. // Load lodash and expose it to the bad extensions/shims.
lodashBizarro = (lodashBizarro = require(filePath))._ || lodashBizarro['defa ult'] || lodashBizarro; lodashBizarro = (lodashBizarro = require(filePath))._ || lodashBizarro['defa ult'] || lodashBizarro;
root._ = oldDash;
// Restore built-in methods. // Restore built-in methods.
setProperty(Array, 'isArray', _isArray); if (_getOwnPropertySymbols) {
setProperty(Date, 'now', _now); Object.getOwnPropertySymbols = _getOwnPropertySymbols;
setProperty(Object, 'getPrototypeOf', _getPrototypeOf);
setProperty(Object, 'keys', _keys);
setProperty(objectProto, 'propertyIsEnumerable', _propertyIsEnumerable);
setProperty(root, 'parseInt', _parseInt);
if (_isFinite) {
setProperty(Number, 'isFinite', _isFinite);
} else { } else {
delete Number.isFinite; delete Object.getOwnPropertySymbols;
} }
if (_ArrayBuffer) { if (Map) {
setProperty(root, 'ArrayBuffer', _ArrayBuffer); setProperty(root, 'Map', Map);
} else { } else {
delete root.ArrayBuffer; delete root.Map;
} }
if (_Set) { if (Set) {
setProperty(root, 'Set', Set); setProperty(root, 'Set', Set);
} else { } else {
delete root.Set; delete root.Set;
} }
if (_WeakMap) { if (Symbol) {
setProperty(root, 'Symbol', Symbol);
} else {
delete root.Symbol;
}
if (WeakMap) {
setProperty(root, 'WeakMap', WeakMap); setProperty(root, 'WeakMap', WeakMap);
} else { } else {
delete root.WeakMap; delete root.WeakMap;
} }
setProperty(objectProto, 'propertyIsEnumerable', _propertyIsEnumerable);
setProperty(Object, 'create', create);
delete root.WinRTError; delete root.WinRTError;
delete root.window;
delete funcProto._method; delete funcProto._method;
}()); }());
// Add values from an iframe. // Add other realm values from the `vm` module.
(function() { lodashStable.attempt(function() {
if (_._object || !document) { lodashStable.assign(realm, require('vm').runInNewContext([
return; '(function() {',
} ' var noop = function() {},',
' root = this;',
'',
' var object = {',
" 'arguments': (function() { return arguments; }(1, 2, 3)),",
" 'array': [1, 2, 3],",
" 'arrayBuffer': new (root.ArrayBuffer || noop),",
" 'boolean': Object(false),",
" 'date': new Date,",
" 'errors': [new Error, new EvalError, new RangeError, new ReferenceErr
or, new SyntaxError, new TypeError, new URIError],",
" 'function': noop,",
" 'map': new (root.Map || noop),",
" 'nan': NaN,",
" 'null': null,",
" 'number': Object(0),",
" 'object': { 'a': 1, 'b': 2, 'c': 3 },",
" 'regexp': /x/,",
" 'set': new (root.Set || noop),",
" 'string': Object('a'),",
" 'symbol': Object((root.Symbol || noop)()),",
" 'undefined': undefined",
' };',
'',
" ['" + typedArrays.join("', '") + "'].forEach(function(type) {",
" var Ctor = root[type]",
' if (Ctor) {',
" object[type.toLowerCase()] = new Ctor(new ArrayBuffer(24));",
' }',
" });",
'',
' return object;',
'}())'
].join('\n')));
});
// Add other realm values from an iframe.
lodashStable.attempt(function() {
_._realm = realm;
var iframe = document.createElement('iframe'); var iframe = document.createElement('iframe');
iframe.frameBorder = iframe.height = iframe.width = 0; iframe.frameBorder = iframe.height = iframe.width = 0;
body.appendChild(iframe); body.appendChild(iframe);
var idoc = (idoc = iframe.contentDocument || iframe.contentWindow).document || idoc; var idoc = (idoc = iframe.contentDocument || iframe.contentWindow).document || idoc;
idoc.write([ idoc.write([
'<script>', '<script>',
'parent._._arguments = (function() { return arguments; }(1, 2, 3));', 'var _ = parent._;',
'parent._._array = [1, 2, 3];', '',
'parent._._boolean = Object(false);', ' var noop = function() {},',
'parent._._date = new Date;', ' root = this;',
"parent._._element = document.createElement('div');",
'parent._._errors = [new Error, new EvalError, new RangeError, new Referen
ceError, new SyntaxError, new TypeError, new URIError];',
'parent._._function = function() {};',
'parent._._nan = NaN;',
'parent._._null = null;',
'parent._._number = Object(0);',
"parent._._object = { 'a': 1, 'b': 2, 'c': 3 };",
'parent._._regexp = /x/;',
"parent._._string = Object('a');",
'parent._._undefined = undefined;',
'', '',
'var root = this;', 'var object = {',
"parent._.each(['" + typedArrays.join("', '") + "'], function(type) {", " 'arguments': (function() { return arguments; }(1, 2, 3)),",
" 'array': [1, 2, 3],",
" 'arrayBuffer': new (root.ArrayBuffer || noop),",
" 'boolean': Object(false),",
" 'date': new Date,",
" 'errors': [new Error, new EvalError, new RangeError, new ReferenceError
, new SyntaxError, new TypeError, new URIError],",
" 'function': noop,",
" 'map': new (root.Map || noop),",
" 'nan': NaN,",
" 'null': null,",
" 'number': Object(0),",
" 'object': { 'a': 1, 'b': 2, 'c': 3 },",
" 'regexp': /x/,",
" 'set': new (root.Set || noop),",
" 'string': Object('a'),",
" 'symbol': Object((root.Symbol || noop)()),",
" 'undefined': undefined",
'};',
'',
"_.each(['" + typedArrays.join("', '") + "'], function(type) {",
' var Ctor = root[type];', ' var Ctor = root[type];',
' if (Ctor) {', ' if (Ctor) {',
" parent._['_' + type.toLowerCase()] = new Ctor(new ArrayBuffer(24));", " object[type.toLowerCase()] = new Ctor(new ArrayBuffer(24));",
' }', ' }',
'});', '});',
'',
'_.assign(_._realm, object);',
'<\/script>' '<\/script>'
].join('\n')); ].join('\n'));
idoc.close(); idoc.close();
}()); delete _._realm;
});
// Add a web worker. // Add a web worker.
(function() { lodashStable.attempt(function() {
if (!Worker) {
return;
}
var worker = new Worker('./asset/worker.js?t=' + (+new Date)); var worker = new Worker('./asset/worker.js?t=' + (+new Date));
worker.addEventListener('message', function(e) { worker.addEventListener('message', function(e) {
_._VERSION = e.data || ''; _._VERSION = e.data || '';
}, false); }, false);
worker.postMessage(ui.buildPath); worker.postMessage(ui.buildPath);
}()); });
// Expose internal modules for better code coverage.
lodashStable.attempt(function() {
var path = require('path'),
basePath = path.dirname(filePath);
if (isModularize && !(amd || isNpm)) {
lodashStable.each([
'internal/baseEach',
'internal/isIndex',
'internal/isIterateeCall'
], function(relPath) {
var func = require(path.join(basePath, relPath)),
funcName = path.basename(relPath);
_['_' + funcName] = func[funcName] || func['default'] || func;
});
}
});
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
if (params) {
console.log('test.js invoked with arguments: ' + JSON.stringify(slice.call(p
arams)));
}
QUnit.module(basename); QUnit.module(basename);
(function() { (function() {
test('should support loading ' + basename + ' as the "lodash" module', 1, fu QUnit.test('should support loading ' + basename + ' as the "lodash" module',
nction() { function(assert) {
assert.expect(1);
if (amd) { if (amd) {
strictEqual((lodashModule || {}).moduleName, 'lodash'); assert.strictEqual((lodashModule || {}).moduleName, 'lodash');
} }
else { else {
skipTest(); skipTest(assert);
} }
}); });
test('should support loading ' + basename + ' with the Require.js "shim" con QUnit.test('should support loading ' + basename + ' with the Require.js "shi
figuration option', 1, function() { m" configuration option', function(assert) {
if (amd && _.includes(ui.loaderPath, 'requirejs')) { assert.expect(1);
strictEqual((shimmedModule || {}).moduleName, 'shimmed');
if (amd && lodashStable.includes(ui.loaderPath, 'requirejs')) {
assert.strictEqual((shimmedModule || {}).moduleName, 'shimmed');
} else { } else {
skipTest(); skipTest(assert);
} }
}); });
test('should support loading ' + basename + ' as the "underscore" module', 1 QUnit.test('should support loading ' + basename + ' as the "underscore" modu
, function() { le', function(assert) {
assert.expect(1);
if (amd) { if (amd) {
strictEqual((underscoreModule || {}).moduleName, 'underscore'); assert.strictEqual((underscoreModule || {}).moduleName, 'underscore');
} }
else { else {
skipTest(); skipTest(assert);
} }
}); });
asyncTest('should support loading ' + basename + ' in a web worker', 1, func QUnit.test('should support loading ' + basename + ' in a web worker', functi
tion() { on(assert) {
assert.expect(1);
var done = assert.async();
if (Worker) { if (Worker) {
var limit = 30000 / QUnit.config.asyncRetries, var limit = 30000 / QUnit.config.asyncRetries,
start = +new Date; start = +new Date;
var attempt = function() { var attempt = function() {
var actual = _._VERSION; var actual = _._VERSION;
if ((new Date - start) < limit && typeof actual != 'string') { if ((new Date - start) < limit && typeof actual != 'string') {
setTimeout(attempt, 16); setTimeout(attempt, 16);
return; return;
} }
strictEqual(actual, _.VERSION); assert.strictEqual(actual, _.VERSION);
QUnit.start(); done();
}; };
attempt(); attempt();
} }
else { else {
skipTest(); skipTest(assert);
QUnit.start(); done();
} }
}); });
test('should not add `Function.prototype` extensions to lodash', 1, function QUnit.test('should not add `Function.prototype` extensions to lodash', funct
() { ion(assert) {
assert.expect(1);
if (lodashBizarro) { if (lodashBizarro) {
ok(!('_method' in lodashBizarro)); assert.notOk('_method' in lodashBizarro);
} }
else { else {
skipTest(); skipTest(assert);
} }
}); });
test('should avoid overwritten native methods', 12, function() { QUnit.test('should avoid overwritten native methods', function(assert) {
function Foo() {} assert.expect(6);
function message(lodashMethod, nativeMethod) { function message(lodashMethod, nativeMethod) {
return '`' + lodashMethod + '` should avoid overwritten native `' + nati veMethod + '`'; return '`' + lodashMethod + '` should avoid overwritten native `' + nati veMethod + '`';
} }
function Foo() { this.a = 1; }
Foo.prototype.b = 2;
var object = { 'a': 1 }, var object = { 'a': 1 },
otherObject = { 'b': 2 }, otherObject = { 'b': 2 },
largeArray = _.times(LARGE_ARRAY_SIZE, _.constant(object)); largeArray = lodashStable.times(LARGE_ARRAY_SIZE, lodashStable.constan t(object));
if (lodashBizarro) { if (lodashBizarro) {
try { try {
var actual = [lodashBizarro.isArray([]), lodashBizarro.isArray({ 'leng var actual = lodashBizarro.keysIn(new Foo).sort();
th': 0 })]; } catch (e) {
} catch(e) {
actual = null; actual = null;
} }
deepEqual(actual, [true, false], message('_.isArray', 'Array.isArray')); var label = message('_.keysIn', 'Object#propertyIsEnumerable');
assert.deepEqual(actual, ['a', 'b'], label);
try { try {
actual = lodashBizarro.now(); actual = [
} catch(e) { lodashBizarro.difference([object, otherObject], largeArray),
lodashBizarro.intersection(largeArray, [object]),
lodashBizarro.uniq(largeArray)
];
} catch (e) {
actual = null; actual = null;
} }
ok(typeof actual == 'number', message('_.now', 'Date.now')); label = message('_.difference`, `_.intersection`, and `_.uniq', 'Object.
create` and `Map');
assert.deepEqual(actual, [[otherObject], [object], [object]], label);
try { try {
actual = [lodashBizarro.isPlainObject({}), lodashBizarro.isPlainObject if (Symbol) {
([])]; object[symbol] = {};
} catch(e) { }
actual = [
lodashBizarro.clone(object),
lodashBizarro.cloneDeep(object)
];
} catch (e) {
actual = null; actual = null;
} }
deepEqual(actual, [true, false], message('_.isPlainObject', 'Object.getP label = message('_.clone` and `_.cloneDeep', 'Object.getOwnPropertySymbo
rototypeOf')); ls');
assert.deepEqual(actual, [object, object], label);
try { try {
actual = [lodashBizarro.keys(object), lodashBizarro.keys()]; var symObject = Object(symbol);
} catch(e) { symObject.constructor = Object;
actual = [
Symbol ? lodashBizarro.clone(symObject) : {},
Symbol ? lodashBizarro.isEqual(symObject, Object(symbol)) : false,
Symbol ? lodashBizarro.toString(symObject) : ''
];
} catch (e) {
actual = null; actual = null;
} }
deepEqual(actual, [['a'], []], message('_.keys', 'Object.keys')); label = message('_.clone`, `_.isEqual`, and `_.toString', 'Symbol');
assert.deepEqual(actual, [{}, false, ''], label);
try { try {
actual = [lodashBizarro.isFinite(1), lodashBizarro.isFinite(NaN)]; var map = new lodashBizarro.memoize.Cache;
} catch(e) { actual = map.set('a', 1).get('a');
} catch (e) {
actual = null; actual = null;
} }
deepEqual(actual, [true, false], message('_.isFinite', 'Number.isFinite' label = message('_.memoize.Cache', 'Map');
)); assert.deepEqual(actual, 1, label);
try { try {
actual = [ map = new (Map || Object);
lodashBizarro.difference([object, otherObject], largeArray), if (Symbol && Symbol.iterator) {
lodashBizarro.intersection(largeArray, [object]), map[Symbol.iterator] = null;
lodashBizarro.uniq(largeArray) }
]; actual = lodashBizarro.toArray(map);
} catch(e) { } catch (e) {
actual = null; actual = null;
} }
deepEqual(actual, [[otherObject], [object], [object]], message('_.differ label = message('_.toArray', 'Map');
ence`, `_.intersection`, and `_.uniq', 'Set')); assert.deepEqual(actual, [], label);
}
else {
skipTest(assert, 6);
}
});
}());
try { /*--------------------------------------------------------------------------*/
actual = _.map(['6', '08', '10'], lodashBizarro.parseInt);
} catch(e) {
actual = null;
}
deepEqual(actual, [6, 8, 10], '`_.parseInt` should work in its bizarro f
orm');
if (ArrayBuffer) { QUnit.module('isIndex');
try {
var buffer = new ArrayBuffer(10); (function() {
actual = lodashBizarro.clone(buffer); var func = _._isIndex;
} catch(e) {
actual = null; QUnit.test('should return `true` for indexes', function(assert) {
} assert.expect(1);
deepEqual(actual, buffer, message('_.clone', 'ArrayBuffer#slice'));
notStrictEqual(actual, buffer, message('_.clone', 'ArrayBuffer#slice') if (func) {
); var values = [[0], ['0'], ['1'], [3, 4], [MAX_SAFE_INTEGER - 1]],
} expected = lodashStable.map(values, alwaysTrue);
else {
skipTest(2); var actual = lodashStable.map(values, function(args) {
} return func.apply(undefined, args);
if (ArrayBuffer && Uint8Array) { });
try {
var array = new Uint8Array(new ArrayBuffer(10)); assert.deepEqual(actual, expected);
actual = lodashBizarro.cloneDeep(array); }
} catch(e) { else {
actual = null; skipTest(assert);
} }
deepEqual(actual, array, message('_.cloneDeep', 'Float64Array')); });
notStrictEqual(actual && actual.buffer, array.buffer, message('_.clone
Deep', 'Float64Array')); QUnit.test('should return `false` for non-indexes', function(assert) {
notStrictEqual(actual, array, message('_.cloneDeep', 'Float64Array')); assert.expect(1);
}
else { if (func) {
skipTest(3); var values = [['1abc'], ['07'], ['0001'], [-1], [3, 3], [1.1], [MAX_SAFE
_INTEGER]],
expected = lodashStable.map(values, alwaysFalse);
var actual = lodashStable.map(values, function(args) {
return func.apply(undefined, args);
});
assert.deepEqual(actual, expected);
}
else {
skipTest(assert);
}
});
}());
/*--------------------------------------------------------------------------*/
QUnit.module('isIterateeCall');
(function() {
var array = [1],
func = _._isIterateeCall,
object = { 'a': 1 };
QUnit.test('should return `true` for iteratee calls', function(assert) {
assert.expect(3);
function Foo() {}
Foo.prototype.a = 1;
if (func) {
assert.strictEqual(func(1, 0, array), true);
assert.strictEqual(func(1, 'a', object), true);
assert.strictEqual(func(1, 'a', new Foo), true);
}
else {
skipTest(assert, 3);
}
});
QUnit.test('should return `false` for non-iteratee calls', function(assert)
{
assert.expect(4);
if (func) {
assert.strictEqual(func(2, 0, array), false);
assert.strictEqual(func(1, 1.1, array), false);
assert.strictEqual(func(1, 0, { 'length': MAX_SAFE_INTEGER + 1 }), false
);
assert.strictEqual(func(1, 'b', object), false);
}
else {
skipTest(assert, 4);
}
});
QUnit.test('should work with `NaN` values', function(assert) {
assert.expect(2);
if (func) {
assert.strictEqual(func(NaN, 0, [NaN]), true);
assert.strictEqual(func(NaN, 'a', { 'a': NaN }), true);
}
else {
skipTest(assert, 2);
}
});
QUnit.test('should not error when `index` is an object without a `toString`
method', function(assert) {
assert.expect(1);
if (func) {
try {
var actual = func(1, { 'toString': null }, [1]);
} catch (e) {
var message = e.message;
} }
assert.strictEqual(actual, false, message || '');
} }
else { else {
skipTest(12); skipTest(assert);
} }
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash constructor'); QUnit.module('lodash constructor');
(function() { (function() {
var values = empties.concat(true, 1, 'a'), var values = empties.concat(true, 1, 'a'),
expected = _.map(values, _.constant(true)); expected = lodashStable.map(values, alwaysTrue);
QUnit.test('should create a new instance when called without the `new` opera
tor', function(assert) {
assert.expect(1);
test('creates a new instance when called without the `new` operator', 1, fun ction() {
if (!isNpm) { if (!isNpm) {
var actual = _.map(values, function(value) { var actual = lodashStable.map(values, function(value) {
return _(value) instanceof _; return _(value) instanceof _;
}); });
deepEqual(actual, expected); assert.deepEqual(actual, expected);
} }
else { else {
skipTest(); skipTest(assert);
} }
}); });
test('should return provided `lodash` instances', 1, function() { QUnit.test('should return provided `lodash` instances', function(assert) {
assert.expect(1);
if (!isNpm) { if (!isNpm) {
var actual = _.map(values, function(value) { var actual = lodashStable.map(values, function(value) {
var wrapped = _(value); var wrapped = _(value);
return _(wrapped) === wrapped; return _(wrapped) === wrapped;
}); });
deepEqual(actual, expected); assert.deepEqual(actual, expected);
} }
else { else {
skipTest(); skipTest(assert);
} }
}); });
test('should convert foreign wrapped values to `lodash` instances', 1, funct QUnit.test('should convert foreign wrapped values to `lodash` instances', fu
ion() { nction(assert) {
assert.expect(1);
if (!isNpm && lodashBizarro) { if (!isNpm && lodashBizarro) {
var actual = _.map(values, function(value) { var actual = lodashStable.map(values, function(value) {
var wrapped = _(lodashBizarro(value)), var wrapped = _(lodashBizarro(value)),
unwrapped = wrapped.value(); unwrapped = wrapped.value();
return wrapped instanceof _ && return wrapped instanceof _ &&
(unwrapped === value || (_.isNaN(unwrapped) && _.isNaN(value))); ((unwrapped === value) || (unwrapped !== unwrapped && value !== valu e));
}); });
deepEqual(actual, expected); assert.deepEqual(actual, expected);
} }
else { else {
skipTest(); skipTest(assert);
}
});
}());
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.add');
(function() {
QUnit.test('should add two numbers', function(assert) {
assert.expect(3);
assert.strictEqual(_.add(6, 4), 10);
assert.strictEqual(_.add(-6, 4), -2);
assert.strictEqual(_.add(-6, -4), -10);
});
QUnit.test('should not coerce arguments to numbers', function(assert) {
assert.expect(2);
assert.strictEqual(_.add('6', '4'), '64');
assert.strictEqual(_.add('x', 'y'), 'xy');
});
QUnit.test('should work with only an `augend` or `addend`', function(assert)
{
assert.expect(3);
assert.strictEqual(_.add(6), 6);
assert.strictEqual(_.add(6, undefined), 6);
assert.strictEqual(_.add(undefined, 4), 4);
});
QUnit.test('should return an unwrapped value when implicitly chaining', func
tion(assert) {
assert.expect(1);
if (!isNpm) {
assert.strictEqual(_(1).add(2), 3);
}
else {
skipTest(assert);
}
});
QUnit.test('should return a wrapped value when explicitly chaining', functio
n(assert) {
assert.expect(1);
if (!isNpm) {
assert.ok(_(1).chain().add(2) instanceof _);
}
else {
skipTest(assert);
} }
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.after'); QUnit.module('lodash.after');
(function() { (function() {
function after(n, times) { function after(n, times) {
var count = 0; var count = 0;
_.times(times, _.after(n, function() { count++; })); lodashStable.times(times, _.after(n, function() { count++; }));
return count; return count;
} }
test('should create a function that invokes `func` after `n` calls', 4, func
tion() {
strictEqual(after(5, 5), 1, 'after(n) should invoke `func` after being cal
led `n` times');
strictEqual(after(5, 4), 0, 'after(n) should not invoke `func` before bein
g called `n` times');
strictEqual(after(0, 0), 0, 'after(0) should not invoke `func` immediately
');
strictEqual(after(0, 1), 1, 'after(0) should invoke `func` when called onc
e');
});
test('should coerce non-finite `n` values to `0`', 1, function() {
var values = [-Infinity, NaN, Infinity],
expected = _.map(values, _.constant(1));
var actual = _.map(values, function(n) { QUnit.test('should create a function that invokes `func` after `n` calls', f
return after(n, 1); unction(assert) {
}); assert.expect(4);
deepEqual(actual, expected); assert.strictEqual(after(5, 5), 1, 'after(n) should invoke `func` after be
ing called `n` times');
assert.strictEqual(after(5, 4), 0, 'after(n) should not invoke `func` befo
re being called `n` times');
assert.strictEqual(after(0, 0), 0, 'after(0) should not invoke `func` imme
diately');
assert.strictEqual(after(0, 1), 1, 'after(0) should invoke `func` when cal
led once');
}); });
test('should allow `func` as the first argument', 1, function() { QUnit.test('should coerce `n` values of `NaN` to `0`', function(assert) {
var count = 0; assert.expect(1);
try {
var after = _.after(function() { count++; }, 1);
after();
after();
} catch(e) {}
strictEqual(count, 2); assert.strictEqual(after(NaN, 1), 1);
}); });
test('should not set a `this` binding', 2, function() { QUnit.test('should not set a `this` binding', function(assert) {
var after = _.after(1, function() { return ++this.count; }), assert.expect(2);
object = { 'count': 0, 'after': after };
var after = _.after(1, function(assert) { return ++this.count; }),
object = { 'after': after, 'count': 0 };
object.after(); object.after();
strictEqual(object.after(), 2); assert.strictEqual(object.after(), 2);
strictEqual(object.count, 2); assert.strictEqual(object.count, 2);
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.ary'); QUnit.module('lodash.ary');
(function() { (function() {
function fn(a, b, c) { function fn(a, b, c) {
return slice.call(arguments); return slice.call(arguments);
} }
test('should cap the numer of params provided to `func`', 2, function() { QUnit.test('should cap the number of arguments provided to `func`', function
var actual = _.map(['6', '8', '10'], _.ary(parseInt, 1)); (assert) {
deepEqual(actual, [6, 8, 10]); assert.expect(2);
var actual = lodashStable.map(['6', '8', '10'], _.ary(parseInt, 1));
assert.deepEqual(actual, [6, 8, 10]);
var capped = _.ary(fn, 2); var capped = _.ary(fn, 2);
deepEqual(capped('a', 'b', 'c', 'd'), ['a', 'b']); assert.deepEqual(capped('a', 'b', 'c', 'd'), ['a', 'b']);
}); });
test('should use `func.length` if `n` is not provided', 1, function() { QUnit.test('should use `func.length` if `n` is not provided', function(asser
t) {
assert.expect(1);
var capped = _.ary(fn); var capped = _.ary(fn);
deepEqual(capped('a', 'b', 'c', 'd'), ['a', 'b', 'c']); assert.deepEqual(capped('a', 'b', 'c', 'd'), ['a', 'b', 'c']);
}); });
test('should treat a negative `n` as `0`', 1, function() { QUnit.test('should treat a negative `n` as `0`', function(assert) {
assert.expect(1);
var capped = _.ary(fn, -1); var capped = _.ary(fn, -1);
try { try {
var actual = capped('a'); var actual = capped('a');
} catch(e) {} } catch (e) {}
deepEqual(actual, []); assert.deepEqual(actual, []);
}); });
test('should work when provided less than the capped numer of arguments', 1, QUnit.test('should coerce `n` to an integer', function(assert) {
function() { assert.expect(1);
var values = ['1', 1.6, 'xyz'],
expected = [['a'], ['a'], []];
var actual = lodashStable.map(values, function(n) {
var capped = _.ary(fn, n);
return capped('a', 'b');
});
assert.deepEqual(actual, expected);
});
QUnit.test('should work when provided less than the capped number of argumen
ts', function(assert) {
assert.expect(1);
var capped = _.ary(fn, 3); var capped = _.ary(fn, 3);
deepEqual(capped('a'), ['a']); assert.deepEqual(capped('a'), ['a']);
}); });
test('should work as an iteratee for `_.map`', 1, function() { QUnit.test('should use the existing `ary` if smaller', function(assert) {
var funcs = _.map([fn], _.ary), assert.expect(1);
var capped = _.ary(_.ary(fn, 1), 2);
assert.deepEqual(capped('a', 'b', 'c'), ['a']);
});
QUnit.test('should work as an iteratee for methods like `_.map`', function(a
ssert) {
assert.expect(1);
var funcs = lodashStable.map([fn], _.ary),
actual = funcs[0]('a', 'b', 'c'); actual = funcs[0]('a', 'b', 'c');
deepEqual(actual, ['a', 'b', 'c']); assert.deepEqual(actual, ['a', 'b', 'c']);
}); });
test('should work when combined with other methods that use metadata', 2, fu QUnit.test('should work when combined with other methods that use metadata',
nction() { function(assert) {
assert.expect(2);
var array = ['a', 'b', 'c'], var array = ['a', 'b', 'c'],
includes = _.curry(_.rearg(_.ary(_.includes, 2), 1, 0), 2); includes = _.curry(_.rearg(_.ary(_.includes, 2), 1, 0), 2);
strictEqual(includes('b')(array, 2), true); assert.strictEqual(includes('b')(array, 2), true);
if (!isNpm) { if (!isNpm) {
includes = _(_.includes).ary(2).rearg(1, 0).curry(2).value(); includes = _(_.includes).ary(2).rearg(1, 0).curry(2).value();
strictEqual(includes('b')(array, 2), true); assert.strictEqual(includes('b')(array, 2), true);
} }
else { else {
skipTest(); skipTest(assert);
} }
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.assign'); QUnit.module('lodash.assignIn');
(function() { (function() {
test('should assign properties of a source object to the destination object' QUnit.test('should be aliased', function(assert) {
, 1, function() { assert.expect(1);
deepEqual(_.assign({ 'a': 1 }, { 'b': 2 }), { 'a': 1, 'b': 2 });
assert.strictEqual(_.extend, _.assignIn);
});
}());
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.assign and lodash.assignIn');
lodashStable.each(['assign', 'assignIn'], function(methodName) {
var func = _[methodName];
QUnit.test('`_.' + methodName + '` should assign source properties to `objec
t`', function(assert) {
assert.expect(1);
assert.deepEqual(func({ 'a': 1 }, { 'b': 2 }), { 'a': 1, 'b': 2 });
}); });
test('should accept multiple source objects', 2, function() { QUnit.test('`_.' + methodName + '` should accept multiple sources', function
(assert) {
assert.expect(2);
var expected = { 'a': 1, 'b': 2, 'c': 3 }; var expected = { 'a': 1, 'b': 2, 'c': 3 };
deepEqual(_.assign({ 'a': 1 }, { 'b': 2 }, { 'c': 3 }), expected); assert.deepEqual(func({ 'a': 1 }, { 'b': 2 }, { 'c': 3 }), expected);
deepEqual(_.assign({ 'a': 1 }, { 'b': 2, 'c': 2 }, { 'c': 3 }), expected); assert.deepEqual(func({ 'a': 1 }, { 'b': 2, 'c': 2 }, { 'c': 3 }), expecte
d);
}); });
test('should overwrite destination properties', 1, function() { QUnit.test('`_.' + methodName + '` should overwrite destination properties',
function(assert) {
assert.expect(1);
var expected = { 'a': 3, 'b': 2, 'c': 1 }; var expected = { 'a': 3, 'b': 2, 'c': 1 };
deepEqual(_.assign({ 'a': 1, 'b': 2 }, expected), expected); assert.deepEqual(func({ 'a': 1, 'b': 2 }, expected), expected);
}); });
test('should assign source properties with `null` and `undefined` values', 1 QUnit.test('`_.' + methodName + '` should assign source properties with null
, function() { ish values', function(assert) {
assert.expect(1);
var expected = { 'a': null, 'b': undefined, 'c': null }; var expected = { 'a': null, 'b': undefined, 'c': null };
deepEqual(_.assign({ 'a': 1, 'b': 2 }, expected), expected); assert.deepEqual(func({ 'a': 1, 'b': 2 }, expected), expected);
}); });
test('should work with a `customizer` callback', 1, function() { QUnit.test('`_.' + methodName + '` should skip assignments if values are the
var actual = _.assign({ 'a': 1, 'b': 2 }, { 'a': 3, 'c': 3 }, function(a, same', function(assert) {
b) { assert.expect(1);
return typeof a == 'undefined' ? b : a;
});
deepEqual(actual, { 'a': 1, 'b': 2, 'c': 3 }); var object = {};
});
test('should work with a `customizer` that returns `undefined`', 1, function var descriptor = {
() { 'configurable': true,
var expected = { 'a': undefined }; 'enumerable': true,
deepEqual(_.assign({}, expected, _.identity), expected); 'set': function() { throw new Error; }
};
var source = {
'a': 1,
'b': undefined,
'c': NaN,
'd': undefined,
'constructor': Object,
'toString': lodashStable.constant('source')
};
defineProperty(object, 'a', lodashStable.assign({}, descriptor, {
'get': alwaysOne
}));
defineProperty(object, 'b', lodashStable.assign({}, descriptor, {
'get': alwaysUndefined
}));
defineProperty(object, 'c', lodashStable.assign({}, descriptor, {
'get': alwaysNaN
}));
defineProperty(object, 'constructor', lodashStable.assign({}, descriptor,
{
'get': lodashStable.constant(Object)
}));
try {
var actual = func(object, source);
} catch (e) {}
assert.deepEqual(actual, source);
}); });
});
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.assignInWith');
(function() {
QUnit.test('should be aliased', function(assert) {
assert.expect(1);
test('should be aliased', 1, function() { assert.strictEqual(_.extendWith, _.assignInWith);
strictEqual(_.extend, _.assign);
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.assignWith and lodash.assignInWith');
lodashStable.each(['assignWith', 'assignInWith'], function(methodName) {
var func = _[methodName];
QUnit.test('`_.' + methodName + '` should work with a `customizer` callback'
, function(assert) {
assert.expect(1);
var actual = func({ 'a': 1, 'b': 2 }, { 'a': 3, 'c': 3 }, function(a, b) {
return a === undefined ? b : a;
});
assert.deepEqual(actual, { 'a': 1, 'b': 2, 'c': 3 });
});
QUnit.test('`_.' + methodName + '` should work with a `customizer` that retu
rns `undefined`', function(assert) {
assert.expect(1);
var expected = { 'a': undefined };
assert.deepEqual(func({}, expected, alwaysUndefined), expected);
});
});
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.at'); QUnit.module('lodash.at');
(function() { (function() {
var args = arguments, var args = arguments,
array = ['a', 'b', 'c']; array = ['a', 'b', 'c'],
object = { 'a': [{ 'b': { 'c': 3 } }, 4] };
array['1.1'] = array['-1'] = 1; QUnit.test('should return the elements corresponding to the specified keys',
function(assert) {
assert.expect(1);
test('should return the elements corresponding to the specified keys', 1, fu nction() {
var actual = _.at(array, [0, 2]); var actual = _.at(array, [0, 2]);
deepEqual(actual, ['a', 'c']); assert.deepEqual(actual, ['a', 'c']);
}); });
test('should return `undefined` for nonexistent keys', 1, function() { QUnit.test('should return `undefined` for nonexistent keys', function(assert
) {
assert.expect(1);
var actual = _.at(array, [2, 4, 0]); var actual = _.at(array, [2, 4, 0]);
deepEqual(actual, ['c', undefined, 'a']); assert.deepEqual(actual, ['c', undefined, 'a']);
}); });
test('should use `undefined` for non-index keys on array-like values', 1, fu QUnit.test('should work with non-index keys on array values', function(asser
nction() { t) {
var values = _.reject(empties, function(value) { assert.expect(1);
return value === 0 || _.isArray(value);
var values = lodashStable.reject(empties, function(value) {
return (value === 0) || lodashStable.isArray(value);
}).concat(-1, 1.1); }).concat(-1, 1.1);
var expected = _.map(values, _.constant(undefined)), var array = lodashStable.transform(values, function(result, value) {
result[value] = 1;
}, []);
var expected = lodashStable.map(values, alwaysOne),
actual = _.at(array, values); actual = _.at(array, values);
deepEqual(actual, expected); assert.deepEqual(actual, expected);
}); });
test('should return an empty array when no keys are provided', 2, function() QUnit.test('should return an empty array when no keys are provided', functio
{ n(assert) {
deepEqual(_.at(array), []); assert.expect(2);
deepEqual(_.at(array, [], []), []);
assert.deepEqual(_.at(array), []);
assert.deepEqual(_.at(array, [], []), []);
}); });
test('should accept multiple key arguments', 1, function() { QUnit.test('should accept multiple key arguments', function(assert) {
assert.expect(1);
var actual = _.at(['a', 'b', 'c', 'd'], 3, 0, 2); var actual = _.at(['a', 'b', 'c', 'd'], 3, 0, 2);
deepEqual(actual, ['d', 'a', 'c']); assert.deepEqual(actual, ['d', 'a', 'c']);
}); });
test('should work with a falsey `collection` argument when keys are provided QUnit.test('should work with a falsey `object` argument when keys are provid
', 1, function() { ed', function(assert) {
var expected = _.map(falsey, _.constant([undefined, undefined])); assert.expect(1);
var actual = _.map(falsey, function(value) { var expected = lodashStable.map(falsey, lodashStable.constant(Array(4)));
var actual = lodashStable.map(falsey, function(object) {
try { try {
return _.at(value, 0, 1); return _.at(object, 0, 1, 'pop', 'push');
} catch(e) {} } catch (e) {}
}); });
deepEqual(actual, expected); assert.deepEqual(actual, expected);
}); });
test('should work with an `arguments` object for `collection`', 1, function( QUnit.test('should work with an `arguments` object for `object`', function(a
) { ssert) {
assert.expect(1);
var actual = _.at(args, [2, 0]); var actual = _.at(args, [2, 0]);
deepEqual(actual, [3, 1]); assert.deepEqual(actual, [3, 1]);
}); });
test('should work with `arguments` object as secondary arguments', 1, functi QUnit.test('should work with `arguments` object as secondary arguments', fun
on() { ction(assert) {
assert.expect(1);
var actual = _.at([1, 2, 3, 4, 5], args); var actual = _.at([1, 2, 3, 4, 5], args);
deepEqual(actual, [2, 3, 4]); assert.deepEqual(actual, [2, 3, 4]);
}); });
test('should work with an object for `collection`', 1, function() { QUnit.test('should work with an object for `object`', function(assert) {
var actual = _.at({ 'a': 1, 'b': 2, 'c': 3 }, ['c', 'a']); assert.expect(1);
deepEqual(actual, [3, 1]);
var actual = _.at(object, ['a[0].b.c', 'a[1]']);
assert.deepEqual(actual, [3, 4]);
}); });
test('should pluck inherited property values', 1, function() { QUnit.test('should pluck inherited property values', function(assert) {
assert.expect(1);
function Foo() { this.a = 1; } function Foo() { this.a = 1; }
Foo.prototype.b = 2; Foo.prototype.b = 2;
var actual = _.at(new Foo, 'b'); var actual = _.at(new Foo, 'b');
deepEqual(actual, [2]); assert.deepEqual(actual, [2]);
}); });
_.each({ QUnit.test('should work in a lazy sequence', function(assert) {
'literal': 'abc', assert.expect(6);
'object': Object('abc')
}, if (!isNpm) {
function(collection, key) { var largeArray = lodashStable.range(LARGE_ARRAY_SIZE),
test('should work with a string ' + key + ' for `collection`', 1, function smallArray = array;
() {
deepEqual(_.at(collection, [2, 0]), ['c', 'a']); lodashStable.each([[2], ['2'], [2, 1]], function(paths) {
}); lodashStable.times(2, function(index) {
var array = index ? largeArray : smallArray,
wrapped = _(array).map(identity).at(paths);
assert.deepEqual(wrapped.value(), _.at(_.map(array, identity), paths
));
});
});
}
else {
skipTest(assert, 6);
}
});
QUnit.test('should support shortcut fusion', function(assert) {
assert.expect(8);
if (!isNpm) {
var array = lodashStable.range(LARGE_ARRAY_SIZE),
count = 0,
iteratee = function(value) { count++; return square(value); },
lastIndex = LARGE_ARRAY_SIZE - 1;
lodashStable.each([lastIndex, lastIndex + '', LARGE_ARRAY_SIZE, []], fun
ction(n, index) {
count = 0;
var actual = _(array).map(iteratee).at(n).value(),
expected = index < 2 ? 1 : 0;
assert.strictEqual(count, expected);
expected = index == 3 ? [] : [index == 2 ? undefined : square(lastInde
x)];
assert.deepEqual(actual, expected);
});
}
else {
skipTest(assert, 8);
}
});
QUnit.test('work with an object for `object` when chaining', function(assert
) {
assert.expect(1);
if (!isNpm) {
var paths = ['a[0].b.c', 'a[1]'],
wrapped = _(object).map(identity).at(paths);
assert.deepEqual(wrapped.value(), _.at(_.map(object, identity), paths));
}
else {
skipTest(assert);
}
}); });
}(1, 2, 3)); }(1, 2, 3));
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.attempt'); QUnit.module('lodash.attempt');
(function() { (function() {
test('should return the result of `func`', 1, function() { QUnit.test('should return the result of `func`', function(assert) {
strictEqual(_.attempt(_.constant('x')), 'x'); assert.expect(1);
assert.strictEqual(_.attempt(lodashStable.constant('x')), 'x');
}); });
test('should return the caught error', 1, function() { QUnit.test('should provide additional arguments to `func`', function(assert)
var expected = _.map(errors, _.constant(true)); {
assert.expect(1);
var actual = _.attempt(function() { return slice.call(arguments); }, 1, 2)
;
assert.deepEqual(actual, [1, 2]);
});
QUnit.test('should return the caught error', function(assert) {
assert.expect(1);
var expected = lodashStable.map(errors, alwaysTrue);
var actual = _.map(errors, function(error) { var actual = lodashStable.map(errors, function(error) {
return _.attempt(function() { throw error; }) === error; return _.attempt(function() { throw error; }) === error;
}); });
deepEqual(actual, expected); assert.deepEqual(actual, expected);
}); });
test('should coerce errors to error objects', 1, function() { QUnit.test('should coerce errors to error objects', function(assert) {
assert.expect(1);
var actual = _.attempt(function() { throw 'x'; }); var actual = _.attempt(function() { throw 'x'; });
ok(_.isEqual(actual, Error('x'))); assert.ok(lodashStable.isEqual(actual, Error('x')));
}); });
test('should work with an error object from another realm', 1, function() { QUnit.test('should work with an error object from another realm', function(a
if (_._object) { ssert) {
var expected = _.map(_._errors, _.constant(true)); assert.expect(1);
if (realm.errors) {
var expected = lodashStable.map(realm.errors, alwaysTrue);
var actual = _.map(_._errors, function(error) { var actual = lodashStable.map(realm.errors, function(error) {
return _.attempt(function() { throw error; }) === error; return _.attempt(function() { throw error; }) === error;
}); });
deepEqual(actual, expected); assert.deepEqual(actual, expected);
} }
else { else {
skipTest(); skipTest(assert);
} }
}); });
test('should return an unwrapped value when chaining', 1, function() { QUnit.test('should return an unwrapped value when implicitly chaining', func
tion(assert) {
assert.expect(1);
if (!isNpm) { if (!isNpm) {
strictEqual(_(_.constant('x')).attempt(), 'x'); assert.strictEqual(_(lodashStable.constant('x')).attempt(), 'x');
} }
else { else {
skipTest(); skipTest(assert);
}
});
QUnit.test('should return a wrapped value when explicitly chaining', functio
n(assert) {
assert.expect(1);
if (!isNpm) {
assert.ok(_(lodashStable.constant('x')).chain().attempt() instanceof _);
}
else {
skipTest(assert);
} }
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.before'); QUnit.module('lodash.before');
(function() { (function() {
function before(n, times) { function before(n, times) {
var count = 0; var count = 0;
_.times(times, _.before(n, function() { count++; })); lodashStable.times(times, _.before(n, function() { count++; }));
return count; return count;
} }
test('should create a function that invokes `func` after `n` calls', 4, func
tion() {
strictEqual(before(5, 4), 4, 'before(n) should invoke `func` before being
called `n` times');
strictEqual(before(5, 6), 4, 'before(n) should not invoke `func` after bei
ng called `n - 1` times');
strictEqual(before(0, 0), 0, 'before(0) should not invoke `func` immediate
ly');
strictEqual(before(0, 1), 0, 'before(0) should not invoke `func` when call
ed');
});
test('should coerce non-finite `n` values to `0`', 1, function() { QUnit.test('should create a function that invokes `func` after `n` calls', f
var values = [-Infinity, NaN, Infinity], unction(assert) {
expected = _.map(values, _.constant(0)); assert.expect(4);
var actual = _.map(values, function(n) { assert.strictEqual(before(5, 4), 4, 'before(n) should invoke `func` before
return before(n); being called `n` times');
}); assert.strictEqual(before(5, 6), 4, 'before(n) should not invoke `func` af
ter being called `n - 1` times');
deepEqual(actual, expected); assert.strictEqual(before(0, 0), 0, 'before(0) should not invoke `func` im
mediately');
assert.strictEqual(before(0, 1), 0, 'before(0) should not invoke `func` wh
en called');
}); });
test('should allow `func` as the first argument', 1, function() { QUnit.test('should coerce `n` values of `NaN` to `0`', function(assert) {
var count = 0; assert.expect(1);
try {
var before = _.before(function() { count++; }, 2);
before();
before();
} catch(e) {}
strictEqual(count, 1); assert.strictEqual(before(NaN, 1), 0);
}); });
test('should not set a `this` binding', 2, function() { QUnit.test('should not set a `this` binding', function(assert) {
var before = _.before(2, function() { return ++this.count; }), assert.expect(2);
object = { 'count': 0, 'before': before };
var before = _.before(2, function(assert) { return ++this.count; }),
object = { 'before': before, 'count': 0 };
object.before(); object.before();
strictEqual(object.before(), 1); assert.strictEqual(object.before(), 1);
strictEqual(object.count, 1); assert.strictEqual(object.count, 1);
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.bind'); QUnit.module('lodash.bind');
(function() { (function() {
function fn() { function fn() {
var result = [this]; var result = [this];
push.apply(result, arguments); push.apply(result, arguments);
return result; return result;
} }
test('should bind a function to an object', 1, function() { QUnit.test('should bind a function to an object', function(assert) {
assert.expect(1);
var object = {}, var object = {},
bound = _.bind(fn, object); bound = _.bind(fn, object);
deepEqual(bound('a'), [object, 'a']); assert.deepEqual(bound('a'), [object, 'a']);
}); });
test('should accept a falsey `thisArg` argument', 1, function() { QUnit.test('should accept a falsey `thisArg` argument', function(assert) {
var values = _.reject(falsey.slice(1), function(value) { return value == n assert.expect(1);
ull; }),
expected = _.map(values, function(value) { return [value]; });
var actual = _.map(values, function(value) { var values = lodashStable.reject(falsey.slice(1), function(value) { return
value == null; }),
expected = lodashStable.map(values, function(value) { return [value];
});
var actual = lodashStable.map(values, function(value) {
try { try {
var bound = _.bind(fn, value); var bound = _.bind(fn, value);
return bound(); return bound();
} catch(e) {} } catch (e) {}
}); });
ok(_.every(actual, function(value, index) { assert.ok(lodashStable.every(actual, function(value, index) {
return _.isEqual(value, expected[index]); return lodashStable.isEqual(value, expected[index]);
})); }));
}); });
test('should bind a function to `null` or `undefined`', 6, function() { QUnit.test('should bind a function to nullish values', function(assert) {
assert.expect(6);
var bound = _.bind(fn, null), var bound = _.bind(fn, null),
actual = bound('a'); actual = bound('a');
ok(actual[0] === null || actual[0] && actual[0].Array); assert.ok((actual[0] === null) || (actual[0] && actual[0].Array));
strictEqual(actual[1], 'a'); assert.strictEqual(actual[1], 'a');
_.times(2, function(index) { lodashStable.times(2, function(index) {
bound = index ? _.bind(fn, undefined) : _.bind(fn); bound = index ? _.bind(fn, undefined) : _.bind(fn);
actual = bound('b'); actual = bound('b');
ok(actual[0] === undefined || actual[0] && actual[0].Array); assert.ok((actual[0] === undefined) || (actual[0] && actual[0].Array));
strictEqual(actual[1], 'b'); assert.strictEqual(actual[1], 'b');
}); });
}); });
test('should partially apply arguments ', 4, function() { QUnit.test('should partially apply arguments ', function(assert) {
assert.expect(4);
var object = {}, var object = {},
bound = _.bind(fn, object, 'a'); bound = _.bind(fn, object, 'a');
deepEqual(bound(), [object, 'a']); assert.deepEqual(bound(), [object, 'a']);
bound = _.bind(fn, object, 'a'); bound = _.bind(fn, object, 'a');
deepEqual(bound('b'), [object, 'a', 'b']); assert.deepEqual(bound('b'), [object, 'a', 'b']);
bound = _.bind(fn, object, 'a', 'b'); bound = _.bind(fn, object, 'a', 'b');
deepEqual(bound(), [object, 'a', 'b']); assert.deepEqual(bound(), [object, 'a', 'b']);
deepEqual(bound('c', 'd'), [object, 'a', 'b', 'c', 'd']); assert.deepEqual(bound('c', 'd'), [object, 'a', 'b', 'c', 'd']);
}); });
test('should support placeholders', 4, function() { QUnit.test('should support placeholders', function(assert) {
assert.expect(4);
var object = {}, var object = {},
ph = _.bind.placeholder, ph = _.bind.placeholder,
bound = _.bind(fn, object, ph, 'b', ph); bound = _.bind(fn, object, ph, 'b', ph);
deepEqual(bound('a', 'c'), [object, 'a', 'b', 'c']); assert.deepEqual(bound('a', 'c'), [object, 'a', 'b', 'c']);
deepEqual(bound('a'), [object, 'a', 'b', undefined]); assert.deepEqual(bound('a'), [object, 'a', 'b', undefined]);
deepEqual(bound('a', 'c', 'd'), [object, 'a', 'b', 'c', 'd']); assert.deepEqual(bound('a', 'c', 'd'), [object, 'a', 'b', 'c', 'd']);
deepEqual(bound(), [object, undefined, 'b', undefined]); assert.deepEqual(bound(), [object, undefined, 'b', undefined]);
}); });
test('should create a function with a `length` of `0`', 2, function() { QUnit.test('should create a function with a `length` of `0`', function(asser
t) {
assert.expect(2);
var fn = function(a, b, c) {}, var fn = function(a, b, c) {},
bound = _.bind(fn, {}); bound = _.bind(fn, {});
strictEqual(bound.length, 0); assert.strictEqual(bound.length, 0);
bound = _.bind(fn, {}, 1); bound = _.bind(fn, {}, 1);
strictEqual(bound.length, 0); assert.strictEqual(bound.length, 0);
}); });
test('should ignore binding when called with the `new` operator', 3, functio QUnit.test('should ignore binding when called with the `new` operator', func
n() { tion(assert) {
assert.expect(3);
function Foo() { function Foo() {
return this; return this;
} }
var bound = _.bind(Foo, { 'a': 1 }), var bound = _.bind(Foo, { 'a': 1 }),
newBound = new bound; newBound = new bound;
strictEqual(newBound.a, undefined); assert.strictEqual(bound().a, 1);
strictEqual(bound().a, 1); assert.strictEqual(newBound.a, undefined);
ok(newBound instanceof Foo); assert.ok(newBound instanceof Foo);
}); });
test('ensure `new bound` is an instance of `func`', 2, function() { QUnit.test('should handle a number of arguments when called with the `new` o
perator', function(assert) {
assert.expect(1);
function Foo() {
return this;
}
function Bar() {}
var thisArg = { 'a': 1 },
boundFoo = _.bind(Foo, thisArg),
boundBar = _.bind(Bar, thisArg),
count = 9,
expected = lodashStable.times(count, lodashStable.constant([undefined,
undefined]));
var actual = lodashStable.times(count, function(index) {
try {
switch (index) {
case 0: return [new boundFoo().a, new boundBar().a];
case 1: return [new boundFoo(1).a, new boundBar(1).a];
case 2: return [new boundFoo(1, 2).a, new boundBar(1, 2).a];
case 3: return [new boundFoo(1, 2, 3).a, new boundBar(1, 2, 3).a];
case 4: return [new boundFoo(1, 2, 3, 4).a, new boundBar(1, 2, 3, 4)
.a];
case 5: return [new boundFoo(1, 2, 3, 4, 5).a, new boundBar(1, 2, 3,
4, 5).a];
case 6: return [new boundFoo(1, 2, 3, 4, 5, 6).a, new boundBar(1, 2,
3, 4, 5, 6).a];
case 7: return [new boundFoo(1, 2, 3, 4, 5, 6, 7).a, new boundBar(1,
2, 3, 4, 5, 6, 7).a];
case 8: return [new boundFoo(1, 2, 3, 4, 5, 6, 7, 8).a, new boundBar
(1, 2, 3, 4, 5, 6, 7, 8).a];
}
} catch (e) {}
});
assert.deepEqual(actual, expected);
});
QUnit.test('should ensure `new bound` is an instance of `func`', function(as
sert) {
assert.expect(2);
function Foo(value) { function Foo(value) {
return value && object; return value && object;
} }
var bound = _.bind(Foo), var bound = _.bind(Foo),
object = {}; object = {};
ok(new bound instanceof Foo); assert.ok(new bound instanceof Foo);
strictEqual(new bound(true), object); assert.strictEqual(new bound(true), object);
}); });
test('should append array arguments to partially applied arguments (test in QUnit.test('should append array arguments to partially applied arguments', f
IE < 9)', 1, function() { unction(assert) {
assert.expect(1);
var object = {}, var object = {},
bound = _.bind(fn, object, 'a'); bound = _.bind(fn, object, 'a');
deepEqual(bound(['b'], 'c'), [object, 'a', ['b'], 'c']); assert.deepEqual(bound(['b'], 'c'), [object, 'a', ['b'], 'c']);
}); });
test('should return a wrapped value when chaining', 2, function() { QUnit.test('should not rebind functions', function(assert) {
if (!isNpm) { assert.expect(3);
var object = {},
bound = _(fn).bind({}, 'a', 'b');
ok(bound instanceof _);
var actual = bound.value()('c');
deepEqual(actual, [object, 'a', 'b', 'c']);
}
else {
skipTest(2);
}
});
test('should rebind functions correctly', 3, function() {
var object1 = {}, var object1 = {},
object2 = {}, object2 = {},
object3 = {}; object3 = {};
var bound1 = _.bind(fn, object1), var bound1 = _.bind(fn, object1),
bound2 = _.bind(bound1, object2, 'a'), bound2 = _.bind(bound1, object2, 'a'),
bound3 = _.bind(bound1, object3, 'b'); bound3 = _.bind(bound1, object3, 'b');
deepEqual(bound1(), [object1]); assert.deepEqual(bound1(), [object1]);
deepEqual(bound2(), [object1, 'a']); assert.deepEqual(bound2(), [object1, 'a']);
deepEqual(bound3(), [object1, 'b']); assert.deepEqual(bound3(), [object1, 'b']);
}); });
}());
/*--------------------------------------------------------------------------*/ QUnit.test('should not error when instantiating bound built-ins', function(a
ssert) {
assert.expect(2);
QUnit.module('lodash.bindAll'); var Ctor = _.bind(Date, null),
expected = new Date(2012, 4, 23, 0, 0, 0, 0);
(function() { try {
var args = arguments; var actual = new Ctor(2012, 4, 23, 0, 0, 0, 0);
} catch (e) {}
test('should bind all methods of `object`', 1, function() { assert.deepEqual(actual, expected);
function Foo() {
this._a = 1; Ctor = _.bind(Date, null, 2012, 4, 23);
this._b = 2;
this.a = function() { return this._a; }; try {
actual = new Ctor(0, 0, 0, 0);
} catch (e) {}
assert.deepEqual(actual, expected);
});
QUnit.test('should not error when calling bound class constructors with the
`new` operator', function(assert) {
assert.expect(1);
var createCtor = lodashStable.attempt(Function, '"use strict";return class
A{}');
if (typeof createCtor == 'function') {
var bound = _.bind(createCtor()),
count = 8,
expected = lodashStable.times(count, alwaysTrue);
var actual = lodashStable.times(count, function(index) {
try {
switch (index) {
case 0: return !!(new bound);
case 1: return !!(new bound(1));
case 2: return !!(new bound(1, 2));
case 3: return !!(new bound(1, 2, 3));
case 4: return !!(new bound(1, 2, 3, 4));
case 5: return !!(new bound(1, 2, 3, 4, 5));
case 6: return !!(new bound(1, 2, 3, 4, 5, 6));
case 7: return !!(new bound(1, 2, 3, 4, 5, 6, 7));
}
} catch (e) {}
});
assert.deepEqual(actual, expected);
}
else {
skipTest(assert);
} }
Foo.prototype.b = function() { return this._b; }; });
var object = new Foo; QUnit.test('should return a wrapped value when chaining', function(assert) {
_.bindAll(object); assert.expect(2);
var actual = _.map(_.functions(object).sort(), function(methodName) { if (!isNpm) {
return object[methodName].call({}); var object = {},
}); bound = _(fn).bind({}, 'a', 'b');
assert.ok(bound instanceof _);
deepEqual(actual, [1, 2]); var actual = bound.value()('c');
assert.deepEqual(actual, [object, 'a', 'b', 'c']);
}
else {
skipTest(assert, 2);
}
}); });
}());
test('should accept individual method names', 1, function() { /*--------------------------------------------------------------------------*/
var object = {
'_a': 1, QUnit.module('lodash.bindAll');
'_b': 2,
'_c': 3, (function() {
'a': function() { return this._a; }, var args = arguments;
'b': function() { return this._b; },
'c': function() { return this._c; } var source = {
}; '_a': 1,
'_b': 2,
'_c': 3,
'_d': 4,
'a': function() { return this._a; },
'b': function() { return this._b; },
'c': function() { return this._c; },
'd': function() { return this._d; }
};
QUnit.test('should accept individual method names', function(assert) {
assert.expect(1);
var object = lodashStable.cloneDeep(source);
_.bindAll(object, 'a', 'b'); _.bindAll(object, 'a', 'b');
var actual = _.map(_.functions(object).sort(), function(methodName) { var actual = lodashStable.map(['a', 'b', 'c'], function(methodName) {
return object[methodName].call({}); return object[methodName].call({});
}); });
deepEqual(actual, [1, 2, undefined]); assert.deepEqual(actual, [1, 2, undefined]);
}); });
test('should accept arrays of method names', 1, function() { QUnit.test('should accept arrays of method names', function(assert) {
var object = { assert.expect(1);
'_a': 1,
'_b': 2,
'_c': 3,
'_d': 4,
'a': function() { return this._a; },
'b': function() { return this._b; },
'c': function() { return this._c; },
'd': function() { return this._d; }
};
var object = lodashStable.cloneDeep(source);
_.bindAll(object, ['a', 'b'], ['c']); _.bindAll(object, ['a', 'b'], ['c']);
var actual = _.map(_.functions(object).sort(), function(methodName) { var actual = lodashStable.map(['a', 'b', 'c', 'd'], function(methodName) {
return object[methodName].call({}); return object[methodName].call({});
}); });
deepEqual(actual, [1, 2, 3, undefined]); assert.deepEqual(actual, [1, 2, 3, undefined]);
}); });
test('should work with an array `object` argument', 1, function() { QUnit.test('should work with an array `object` argument', function(assert) {
assert.expect(1);
var array = ['push', 'pop']; var array = ['push', 'pop'];
_.bindAll(array); _.bindAll(array);
strictEqual(array.pop, arrayProto.pop); assert.strictEqual(array.pop, arrayProto.pop);
}); });
test('should work with `arguments` objects as secondary arguments', 1, funct QUnit.test('should work with `arguments` objects as secondary arguments', fu
ion() { nction(assert) {
var object = { assert.expect(1);
'_a': 1,
'a': function() { return this._a; }
};
var object = lodashStable.cloneDeep(source);
_.bindAll(object, args); _.bindAll(object, args);
var actual = _.map(_.functions(object).sort(), function(methodName) { var actual = lodashStable.map(args, function(methodName) {
return object[methodName].call({}); return object[methodName].call({});
}); });
deepEqual(actual, [1]); assert.deepEqual(actual, [1]);
}); });
}('a')); }('a'));
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.bindKey'); QUnit.module('lodash.bindKey');
(function() { (function() {
test('should work when the target function is overwritten', 2, function() { QUnit.test('should work when the target function is overwritten', function(a
ssert) {
assert.expect(2);
var object = { var object = {
'user': 'fred', 'user': 'fred',
'greet': function(greeting) { 'greet': function(greeting) {
return this.user + ' says: ' + greeting; return this.user + ' says: ' + greeting;
} }
}; };
var bound = _.bindKey(object, 'greet', 'hi'); var bound = _.bindKey(object, 'greet', 'hi');
strictEqual(bound(), 'fred says: hi'); assert.strictEqual(bound(), 'fred says: hi');
object.greet = function(greeting) { object.greet = function(greeting) {
return this.user + ' says: ' + greeting + '!'; return this.user + ' says: ' + greeting + '!';
}; };
strictEqual(bound(), 'fred says: hi!'); assert.strictEqual(bound(), 'fred says: hi!');
}); });
test('should support placeholders', 4, function() { QUnit.test('should support placeholders', function(assert) {
assert.expect(4);
var object = { var object = {
'fn': function() { 'fn': function() {
return slice.call(arguments); return slice.call(arguments);
} }
}; };
var ph = _.bindKey.placeholder, var ph = _.bindKey.placeholder,
bound = _.bindKey(object, 'fn', ph, 'b', ph); bound = _.bindKey(object, 'fn', ph, 'b', ph);
deepEqual(bound('a', 'c'), ['a', 'b', 'c']); assert.deepEqual(bound('a', 'c'), ['a', 'b', 'c']);
deepEqual(bound('a'), ['a', 'b', undefined]); assert.deepEqual(bound('a'), ['a', 'b', undefined]);
deepEqual(bound('a', 'c', 'd'), ['a', 'b', 'c', 'd']); assert.deepEqual(bound('a', 'c', 'd'), ['a', 'b', 'c', 'd']);
deepEqual(bound(), [undefined, 'b', undefined]); assert.deepEqual(bound(), [undefined, 'b', undefined]);
});
QUnit.test('should ensure `new bound` is an instance of `object[key]`', func
tion(assert) {
assert.expect(2);
function Foo(value) {
return value && object;
}
var object = { 'Foo': Foo },
bound = _.bindKey(object, 'Foo');
assert.ok(new bound instanceof Foo);
assert.strictEqual(new bound(true), object);
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('case methods'); QUnit.module('case methods');
_.each(['camel', 'kebab', 'snake'], function(caseName) { lodashStable.each(['camel', 'kebab', 'lower', 'snake', 'start', 'upper'], func tion(caseName) {
var methodName = caseName + 'Case', var methodName = caseName + 'Case',
func = _[methodName]; func = _[methodName];
var strings = [ var strings = [
'foo bar', 'Foo bar', 'foo Bar', 'Foo Bar', 'foo bar', 'Foo bar', 'foo Bar', 'Foo Bar',
'FOO BAR', 'fooBar', '--foo-bar', '__foo_bar__' 'FOO BAR', 'fooBar', '--foo-bar', '__foo_bar__'
]; ];
var expected = (function() { var converted = (function() {
switch (caseName) { switch (caseName) {
case 'camel': return 'fooBar'; case 'camel': return 'fooBar';
case 'kebab': return 'foo-bar'; case 'kebab': return 'foo-bar';
case 'lower': return 'foo bar';
case 'snake': return 'foo_bar'; case 'snake': return 'foo_bar';
case 'start': return 'Foo Bar';
case 'upper': return 'FOO BAR';
} }
}()); }());
test('`_.' + methodName + '` should convert `string` to ' + caseName + ' cas QUnit.test('`_.' + methodName + '` should convert `string` to ' + caseName +
e', 1, function() { ' case', function(assert) {
var actual = _.map(strings, function(string) { assert.expect(1);
return func(string) === expected;
var actual = lodashStable.map(strings, function(string) {
return func(string) === converted;
}); });
deepEqual(actual, _.map(strings, _.constant(true))); assert.deepEqual(actual, lodashStable.map(strings, alwaysTrue));
}); });
test('`_.' + methodName + '` should handle double-converting strings', 1, fu QUnit.test('`_.' + methodName + '` should handle double-converting strings',
nction() { function(assert) {
var actual = _.map(strings, function(string) { assert.expect(1);
return func(func(string)) === expected;
var actual = lodashStable.map(strings, function(string) {
return func(func(string)) === converted;
}); });
deepEqual(actual, _.map(strings, _.constant(true))); assert.deepEqual(actual, lodashStable.map(strings, alwaysTrue));
}); });
test('`_.' + methodName + '` should deburr letters', 1, function() { QUnit.test('`_.' + methodName + '` should deburr letters', function(assert)
var actual = _.map(burredLetters, function(burred, index) { {
return func(burred) === deburredLetters[index].toLowerCase(); assert.expect(1);
var actual = lodashStable.map(burredLetters, function(burred, index) {
var letter = deburredLetters[index];
if (caseName == 'start') {
letter = lodashStable.capitalize(letter);
} else if (caseName == 'upper') {
letter = letter.toUpperCase();
} else {
letter = letter.toLowerCase();
}
return func(burred) === letter;
}); });
deepEqual(actual, _.map(burredLetters, _.constant(true))); assert.deepEqual(actual, lodashStable.map(burredLetters, alwaysTrue));
}); });
test('should trim latin-1 mathematical operators', 1, function() { QUnit.test('`_.' + methodName + '` should trim latin-1 mathematical operator
var actual = _.map(['\xd7', '\xf7'], func); s', function(assert) {
deepEqual(actual, ['', '']); assert.expect(1);
var actual = lodashStable.map(['\xd7', '\xf7'], func);
assert.deepEqual(actual, ['', '']);
}); });
test('`_.' + methodName + '` should coerce `string` to a string', 2, functio QUnit.test('`_.' + methodName + '` should coerce `string` to a string', func
n() { tion(assert) {
var string = 'Foo Bar'; assert.expect(2);
strictEqual(func(Object(string)), expected);
strictEqual(func({ 'toString': _.constant(string) }), expected); var string = 'foo bar';
assert.strictEqual(func(Object(string)), converted);
assert.strictEqual(func({ 'toString': lodashStable.constant(string) }), co
nverted);
}); });
test('`_.' + methodName + '` should return an unwrapped value when chaining' QUnit.test('`_.' + methodName + '` should return an unwrapped value implicit
, 1, function() { ly when chaining', function(assert) {
assert.expect(1);
if (!isNpm) { if (!isNpm) {
strictEqual(_('foo bar')[methodName](), expected); assert.strictEqual(_('foo bar')[methodName](), converted);
} }
else { else {
skipTest(); skipTest(assert);
}
});
QUnit.test('`_.' + methodName + '` should return a wrapped value when explic
itly chaining', function(assert) {
assert.expect(1);
if (!isNpm) {
assert.ok(_('foo bar').chain()[methodName]() instanceof _);
}
else {
skipTest(assert);
} }
}); });
}); });
(function() {
QUnit.test('should get the original value after cycling through all case met
hods', function(assert) {
assert.expect(1);
var funcs = [_.camelCase, _.kebabCase, _.snakeCase, _.startCase, _.camelCa
se];
var actual = lodashStable.reduce(funcs, function(result, func) {
return func(result);
}, 'enable 24h format');
assert.strictEqual(actual, 'enable24hFormat');
});
}());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.camelCase'); QUnit.module('lodash.camelCase');
(function() { (function() {
test('should work with numbers', 3, function() { QUnit.test('should work with numbers', function(assert) {
strictEqual(_.camelCase('too legit 2 quit'), 'tooLegit2Quit'); assert.expect(5);
strictEqual(_.camelCase('walk 500 miles'), 'walk500Miles');
strictEqual(_.camelCase('xhr2 request'), 'xhr2Request'); assert.strictEqual(_.camelCase('12 feet'), '12Feet');
assert.strictEqual(_.camelCase('enable 24h format'), 'enable24hFormat');
assert.strictEqual(_.camelCase('too legit 2 quit'), 'tooLegit2Quit');
assert.strictEqual(_.camelCase('walk 500 miles'), 'walk500Miles');
assert.strictEqual(_.camelCase('xhr2 request'), 'xhr2Request');
}); });
test('should handle acronyms', 6, function() { QUnit.test('should handle acronyms', function(assert) {
_.each(['safe HTML', 'safeHTML'], function(string) { assert.expect(6);
strictEqual(_.camelCase(string), 'safeHtml');
lodashStable.each(['safe HTML', 'safeHTML'], function(string) {
assert.strictEqual(_.camelCase(string), 'safeHtml');
}); });
_.each(['escape HTML entities', 'escapeHTMLEntities'], function(string) { lodashStable.each(['escape HTML entities', 'escapeHTMLEntities'], function
strictEqual(_.camelCase(string), 'escapeHtmlEntities'); (string) {
assert.strictEqual(_.camelCase(string), 'escapeHtmlEntities');
}); });
_.each(['XMLHttpRequest', 'XmlHTTPRequest'], function(string) { lodashStable.each(['XMLHttpRequest', 'XmlHTTPRequest'], function(string) {
strictEqual(_.camelCase(string), 'xmlHttpRequest'); assert.strictEqual(_.camelCase(string), 'xmlHttpRequest');
}); });
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.capitalize'); QUnit.module('lodash.capitalize');
(function() { (function() {
test('should capitalize the first character of a string', 3, function() { QUnit.test('should capitalize the first character of a string', function(ass
strictEqual(_.capitalize('fred'), 'Fred'); ert) {
strictEqual(_.capitalize('Fred'), 'Fred'); assert.expect(3);
strictEqual(_.capitalize(' fred'), ' fred');
});
test('should return an unwrapped value when chaining', 1, function() { assert.strictEqual(_.capitalize('fred'), 'Fred');
if (!isNpm) { assert.strictEqual(_.capitalize('Fred'), 'Fred');
strictEqual(_('fred').capitalize(), 'Fred'); assert.strictEqual(_.capitalize(' fred'), ' fred');
}
else {
skipTest();
}
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.chain'); QUnit.module('lodash.chain');
(function() { (function() {
test('should return a wrapped value', 1, function() { QUnit.test('should return a wrapped value', function(assert) {
assert.expect(1);
if (!isNpm) { if (!isNpm) {
var actual = _.chain({ 'a': 0 }); var actual = _.chain({ 'a': 0 });
ok(actual instanceof _); assert.ok(actual instanceof _);
} }
else { else {
skipTest(); skipTest(assert);
} }
}); });
test('should return existing wrapped values', 2, function() { QUnit.test('should return existing wrapped values', function(assert) {
assert.expect(2);
if (!isNpm) { if (!isNpm) {
var wrapped = _({ 'a': 0 }); var wrapped = _({ 'a': 0 });
strictEqual(_.chain(wrapped), wrapped); assert.strictEqual(_.chain(wrapped), wrapped);
strictEqual(wrapped.chain(), wrapped); assert.strictEqual(wrapped.chain(), wrapped);
} }
else { else {
skipTest(2); skipTest(assert, 2);
} }
}); });
test('should enable chaining of methods that return unwrapped values by defa QUnit.test('should enable chaining for methods that return unwrapped values'
ult', 6, function() { , function(assert) {
assert.expect(6);
if (!isNpm) { if (!isNpm) {
var array = ['c', 'b', 'a']; var array = ['c', 'b', 'a'];
ok(_.chain(array).first() instanceof _); assert.ok(_.chain(array).head() instanceof _);
ok(_(array).chain().first() instanceof _); assert.ok(_(array).chain().head() instanceof _);
ok(_.chain(array).isArray() instanceof _); assert.ok(_.chain(array).isArray() instanceof _);
ok(_(array).chain().isArray() instanceof _); assert.ok(_(array).chain().isArray() instanceof _);
ok(_.chain(array).sortBy().first() instanceof _); assert.ok(_.chain(array).sortBy().head() instanceof _);
ok(_(array).chain().sortBy().first() instanceof _); assert.ok(_(array).chain().sortBy().head() instanceof _);
} }
else { else {
skipTest(6); skipTest(assert, 6);
} }
}); });
test('should chain multiple methods', 6, function() { QUnit.test('should chain multiple methods', function(assert) {
assert.expect(6);
if (!isNpm) { if (!isNpm) {
_.times(2, function(index) { lodashStable.times(2, function(index) {
var array = ['one two three four', 'five six seven eight', 'nine ten e leven twelve'], var array = ['one two three four', 'five six seven eight', 'nine ten e leven twelve'],
expected = { ' ': 9, 'e': 14, 'f': 2, 'g': 1, 'h': 2, 'i': 4, 'l': 2, 'n': 6, 'o': 3, 'r': 2, 's': 2, 't': 5, 'u': 1, 'v': 4, 'w': 2, 'x': 1 }, expected = { ' ': 9, 'e': 14, 'f': 2, 'g': 1, 'h': 2, 'i': 4, 'l': 2, 'n': 6, 'o': 3, 'r': 2, 's': 2, 't': 5, 'u': 1, 'v': 4, 'w': 2, 'x': 1 },
wrapped = index ? _(array).chain() : _.chain(array); wrapped = index ? _(array).chain() : _.chain(array);
var actual = wrapped var actual = wrapped
.chain() .chain()
.map(function(value) { return value.split(''); }) .map(function(value) { return value.split(''); })
.flatten() .flatten()
.reduce(function(object, chr) { .reduce(function(object, chr) {
object[chr] || (object[chr] = 0); object[chr] || (object[chr] = 0);
object[chr]++; object[chr]++;
return object; return object;
}, {}) }, {})
.value(); .value();
deepEqual(actual, expected); assert.deepEqual(actual, expected);
array = [1, 2, 3, 4, 5, 6]; array = [1, 2, 3, 4, 5, 6];
wrapped = index ? _(array).chain() : _.chain(array); wrapped = index ? _(array).chain() : _.chain(array);
actual = wrapped actual = wrapped
.chain() .chain()
.filter(function(n) { return n % 2; }) .filter(function(n) { return n % 2 != 0; })
.reject(function(n) { return n % 3 == 0; }) .reject(function(n) { return n % 3 == 0; })
.sortBy(function(n) { return -n; }) .sortBy(function(n) { return -n; })
.value(); .value();
deepEqual(actual, [5, 1]); assert.deepEqual(actual, [5, 1]);
array = [3, 4]; array = [3, 4];
wrapped = index ? _(array).chain() : _.chain(array); wrapped = index ? _(array).chain() : _.chain(array);
actual = wrapped actual = wrapped
.reverse() .reverse()
.concat([2, 1]) .concat([2, 1])
.unshift(5) .unshift(5)
.tap(function(value) { value.pop(); }) .tap(function(value) { value.pop(); })
.map(function(n) { return n * n; }) .map(square)
.value(); .value();
deepEqual(actual,[25, 16, 9, 4]); assert.deepEqual(actual, [25, 16, 9, 4]);
}); });
} }
else { else {
skipTest(6); skipTest(assert, 6);
} }
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.chunk'); QUnit.module('lodash.chunk');
(function() { (function() {
var array = [0, 1, 2, 3, 4, 5]; var array = [0, 1, 2, 3, 4, 5];
test('should return chunked arrays', 1, function() { QUnit.test('should return chunked arrays', function(assert) {
assert.expect(1);
var actual = _.chunk(array, 3); var actual = _.chunk(array, 3);
deepEqual(actual, [[0, 1, 2], [3, 4, 5]]); assert.deepEqual(actual, [[0, 1, 2], [3, 4, 5]]);
}); });
test('should return the last chunk as remaining elements', 1, function() { QUnit.test('should return the last chunk as remaining elements', function(as
sert) {
assert.expect(1);
var actual = _.chunk(array, 4); var actual = _.chunk(array, 4);
deepEqual(actual, [[0, 1, 2, 3], [4, 5]]); assert.deepEqual(actual, [[0, 1, 2, 3], [4, 5]]);
}); });
test('should ensure the minimum `chunkSize` is `1`', 1, function() { QUnit.test('should ensure the minimum `size` is `0`', function(assert) {
assert.expect(1);
var values = falsey.concat(-1, -Infinity), var values = falsey.concat(-1, -Infinity),
expected = _.map(values, _.constant([[0], [1], [2], [3], [4], [5]])); expected = lodashStable.map(values, alwaysEmptyArray);
var actual = _.map(values, function(value, index) { var actual = lodashStable.map(values, function(value, index) {
return index ? _.chunk(array, value) : _.chunk(array); return index ? _.chunk(array, value) : _.chunk(array);
}); });
deepEqual(actual, expected); assert.deepEqual(actual, expected);
});
QUnit.test('should coerce `size` to an integer', function(assert) {
assert.expect(1);
assert.deepEqual(_.chunk(array, array.length / 4), [[0], [1], [2], [3], [4
], [5]]);
});
}());
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.clamp');
(function() {
QUnit.test('should work with a `max` argument', function(assert) {
assert.expect(2);
assert.strictEqual(_.clamp(5, 3), 3);
assert.strictEqual(_.clamp(1, 3), 1);
});
QUnit.test('should clamp negative numbers', function(assert) {
assert.expect(3);
assert.strictEqual(_.clamp(-10, -5, 5), -5);
assert.strictEqual(_.clamp(-10.2, -5.5, 5.5), -5.5);
assert.strictEqual(_.clamp(-Infinity, -5, 5), -5);
});
QUnit.test('should clamp positive numbers', function(assert) {
assert.expect(3);
assert.strictEqual(_.clamp(10, -5, 5), 5);
assert.strictEqual(_.clamp(10.6, -5.6, 5.4), 5.4);
assert.strictEqual(_.clamp(Infinity, -5, 5), 5);
});
QUnit.test('should not alter negative numbers in range', function(assert) {
assert.expect(3);
assert.strictEqual(_.clamp(-4, -5, 5), -4);
assert.strictEqual(_.clamp(-5, -5, 5), -5);
assert.strictEqual(_.clamp(-5.5, -5.6, 5.6), -5.5);
}); });
test('should work as an iteratee for `_.map`', 1, function() { QUnit.test('should not alter positive numbers in range', function(assert) {
var actual = _.map([[1, 2], [3, 4]], _.chunk); assert.expect(3);
deepEqual(actual, [[[1], [2]], [[3], [4]]]);
assert.strictEqual(_.clamp(4, -5, 5), 4);
assert.strictEqual(_.clamp(5, -5, 5), 5);
assert.strictEqual(_.clamp(4.5, -5.1, 5.2), 4.5);
});
QUnit.test('should not alter `0` in range', function(assert) {
assert.expect(1);
assert.strictEqual(1 / _.clamp(0, -5, 5), Infinity);
});
QUnit.test('should clamp to `0`', function(assert) {
assert.expect(1);
assert.strictEqual(1 / _.clamp(-10, 0, 5), Infinity);
});
QUnit.test('should not alter `-0` in range', function(assert) {
assert.expect(1);
assert.strictEqual(1 / _.clamp(-0, -5, 5), -Infinity);
});
QUnit.test('should clamp to `-0`', function(assert) {
assert.expect(1);
assert.strictEqual(1 / _.clamp(-10, -0, 5), -Infinity);
});
QUnit.test('should return `NaN` when `number` is `NaN`', function(assert) {
assert.expect(1);
assert.deepEqual(_.clamp(NaN, -5, 5), NaN);
});
QUnit.test('should coerce `min` and `max` of `NaN` to `0`', function(assert)
{
assert.expect(2);
assert.deepEqual(_.clamp(1, -5, NaN), 0);
assert.deepEqual(_.clamp(-1, NaN, 5), 0);
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('clone methods'); QUnit.module('clone methods');
(function() { (function() {
function Foo() { this.a = 1; } function Foo() { this.a = 1; }
Foo.prototype = { 'b': 1 }; Foo.prototype.b = 1;
Foo.c = function() {}; Foo.c = function() {};
if (Map) {
var map = new Map;
map.set('a', 1);
map.set('b', 2);
}
if (Set) {
var set = new Set;
set.add(1);
set.add(2);
}
var objects = { var objects = {
'`arguments` objects': arguments, '`arguments` objects': arguments,
'arrays': ['a', ''], 'arrays': ['a', ''],
'array-like-objects': { '0': 'a', '1': '', 'length': 3 }, 'array-like-objects': { '0': 'a', '1': '', 'length': 3 },
'booleans': false, 'booleans': false,
'boolean objects': Object(false), 'boolean objects': Object(false),
'date objects': new Date,
'Foo instances': new Foo, 'Foo instances': new Foo,
'objects': { 'a': 0, 'b': 1, 'c': 3 }, 'objects': { 'a': 0, 'b': 1, 'c': 2 },
'objects with object values': { 'a': /a/, 'b': ['B'], 'c': { 'C': 1 } }, 'objects with object values': { 'a': /a/, 'b': ['B'], 'c': { 'C': 1 } },
'objects from another document': _._object || {}, 'objects from another document': realm.object || {},
'maps': map,
'null values': null, 'null values': null,
'numbers': 3, 'numbers': 0,
'number objects': Object(3), 'number objects': Object(0),
'regexes': /a/gim, 'regexes': /a/gim,
'sets': set,
'strings': 'a', 'strings': 'a',
'string objects': Object('a'), 'string objects': Object('a'),
'undefined values': undefined 'undefined values': undefined
}; };
objects['arrays'].length = 3; objects['arrays'].length = 3;
var uncloneable = { var uncloneable = {
'DOM elements': body, 'DOM elements': body,
'functions': Foo 'functions': Foo,
'generators': generator
}; };
_.each(errors, function(error) { lodashStable.each(errors, function(error) {
uncloneable[error.name + 's'] = error; uncloneable[error.name + 's'] = error;
}); });
test('`_.clone` should perform a shallow clone', 2, function() { QUnit.test('`_.clone` should perform a shallow clone', function(assert) {
var expected = [{ 'a': 0 }, { 'b': 1 }], assert.expect(2);
actual = _.clone(expected);
deepEqual(actual, expected);
ok(actual !== expected && actual[0] === expected[0]);
});
test('`_.clone` should work with `isDeep`', 2, function() { var array = [{ 'a': 0 }, { 'b': 1 }],
var expected = [{ 'a': 0 }, { 'b': 1 }], actual = _.clone(array);
actual = _.clone(expected, true);
deepEqual(actual, expected); assert.deepEqual(actual, array);
ok(actual !== expected && actual[0] !== expected[0]); assert.ok(actual !== array && actual[0] === array[0]);
}); });
test('`_.cloneDeep` should deep clone objects with circular references', 1, QUnit.test('`_.cloneDeep` should deep clone objects with circular references
function() { ', function(assert) {
assert.expect(1);
var object = { var object = {
'foo': { 'b': { 'c': { 'd': {} } } }, 'foo': { 'b': { 'c': { 'd': {} } } },
'bar': {} 'bar': {}
}; };
object.foo.b.c.d = object; object.foo.b.c.d = object;
object.bar.b = object.foo.b; object.bar.b = object.foo.b;
var clone = _.cloneDeep(object); var actual = _.cloneDeep(object);
ok(clone.bar.b === clone.foo.b && clone === clone.foo.b.c.d && clone !== o assert.ok(actual.bar.b === actual.foo.b && actual === actual.foo.b.c.d &&
bject); actual !== object);
}); });
_.each(['clone', 'cloneDeep'], function(methodName, index) { QUnit.test('`_.cloneDeep` should deep clone objects with lots of circular re
var func = _[methodName], ferences', function(assert) {
isDeep = !!index; assert.expect(2);
_.forOwn(objects, function(object, key) { var cyclical = {};
test('`_.' + methodName + '` should clone ' + key, 2, function() { lodashStable.times(LARGE_ARRAY_SIZE + 1, function(index) {
var actual = func(object); cyclical['v' + index] = [index ? cyclical['v' + (index - 1)] : cyclical]
ok(_.isEqual(actual, object)); ;
});
if (_.isObject(object)) { var clone = _.cloneDeep(cyclical),
notStrictEqual(actual, object); actual = clone['v' + LARGE_ARRAY_SIZE][0];
} else {
strictEqual(actual, object); assert.strictEqual(actual, clone['v' + (LARGE_ARRAY_SIZE - 1)]);
} assert.notStrictEqual(actual, cyclical['v' + (LARGE_ARRAY_SIZE - 1)]);
}); });
QUnit.test('`_.cloneDeepWith` should provide `stack` to `customizer`', funct
ion(assert) {
assert.expect(164);
var Stack,
keys = [true, false, 1, -Infinity, NaN, {}, null, 'a', symbol || {}, u
ndefined];
var pairs = lodashStable.map(keys, function(key, index) {
var lastIndex = keys.length - 1;
return [key, keys[lastIndex - index]];
}); });
_.forOwn(uncloneable, function(value, key) { _.cloneDeepWith({ 'a': 1 }, function() {
test('`_.' + methodName + '` should not clone ' + key, 3, function() { if (arguments.length > 1) {
var object = { 'a': value, 'b': { 'c': value } }, Stack || (Stack = _.last(arguments).constructor);
actual = func(object); }
});
notStrictEqual(actual, object); var stacks = [new Stack(pairs), new Stack(pairs)];
deepEqual(actual, object);
var expected = typeof value == 'function' ? { 'c': Foo.c } : (value && lodashStable.times(LARGE_ARRAY_SIZE - pairs.length + 1, function() {
{}); stacks[1].set({}, {});
deepEqual(func(value), expected); });
lodashStable.each(stacks, function(stack) {
lodashStable.each(keys, function(key, index) {
var value = pairs[index][1];
assert.deepEqual(stack.get(key), value);
assert.strictEqual(stack.has(key), true);
assert.strictEqual(stack['delete'](key), true);
assert.strictEqual(stack.has(key), false);
assert.strictEqual(stack.get(key), undefined);
assert.strictEqual(stack['delete'](key), false);
assert.strictEqual(stack.set(key, value), stack);
assert.strictEqual(stack.has(key), true);
}); });
test('`_.' + methodName + '` should work with a `customizer` callback an assert.strictEqual(stack.clear(), undefined);
d ' + key, 4, function() { assert.ok(lodashStable.every(keys, function(key) {
var customizer = function(value) { return !stack.has(key);
return _.isPlainObject(value) ? undefined : value; }));
}; });
});
var actual = func(value, customizer); lodashStable.each(['clone', 'cloneDeep'], function(methodName) {
var func = _[methodName],
isDeep = methodName == 'cloneDeep';
deepEqual(actual, value); lodashStable.forOwn(objects, function(object, key) {
strictEqual(actual, value); QUnit.test('`_.' + methodName + '` should clone ' + key, function(assert
) {
assert.expect(2);
var object = { 'a': value, 'b': { 'c': value } }; var isEqual = (key == 'maps' || key == 'sets') ? _.isEqual : lodashSta
actual = func(object, customizer); ble.isEqual,
actual = func(object);
assert.ok(isEqual(actual, object));
deepEqual(actual, object); if (lodashStable.isObject(object)) {
notStrictEqual(actual, object); assert.notStrictEqual(actual, object);
} else {
assert.strictEqual(actual, object);
}
}); });
}); });
test('`_.' + methodName + '` should clone array buffers', 2, function() { QUnit.test('`_.' + methodName + '` should clone array buffers', function(a
ssert) {
assert.expect(2);
if (ArrayBuffer) { if (ArrayBuffer) {
var buffer = new ArrayBuffer(10), var buffer = new ArrayBuffer(10),
actual = func(buffer); actual = func(buffer);
strictEqual(actual.byteLength, buffer.byteLength); assert.strictEqual(actual.byteLength, buffer.byteLength);
notStrictEqual(actual, buffer); assert.notStrictEqual(actual, buffer);
} }
else { else {
skipTest(2); skipTest(assert, 2);
} }
}); });
_.each(typedArrays, function(type) { QUnit.test('`_.' + methodName + '` should clone `index` and `input` array
test('`_.' + methodName + '` should clone ' + type + ' arrays', 10, func properties', function(assert) {
tion() { assert.expect(2);
var Ctor = root[type];
_.times(2, function(index) { var array = /x/.exec('vwxyz'),
if (Ctor) { actual = func(array);
var buffer = new ArrayBuffer(24),
array = index ? new Ctor(buffer, 8, 1) : new Ctor(buffer),
actual = func(array);
deepEqual(actual, array); assert.strictEqual(actual.index, 2);
notStrictEqual(actual, array); assert.strictEqual(actual.input, 'vwxyz');
strictEqual(actual.buffer === array.buffer, !isDeep);
strictEqual(actual.byteOffset, array.byteOffset);
strictEqual(actual.length, array.length);
}
else {
skipTest(5);
}
});
});
}); });
test('`_.' + methodName + '` should clone problem JScript properties (test QUnit.test('`_.' + methodName + '` should clone `lastIndex` regexp propert
in IE < 9)', 2, function() { y', function(assert) {
var actual = func(shadowObject); assert.expect(1);
deepEqual(actual, shadowObject);
notStrictEqual(actual, shadowObject); // Avoid a regexp literal for older Opera and use `exec` for older Safar
i.
var regexp = RegExp('x', 'g');
regexp.exec('vwxyz');
var actual = func(regexp);
assert.strictEqual(actual.lastIndex, 3);
}); });
test('`_.' + methodName + '` should provide the correct `customizer` argum QUnit.test('`_.' + methodName + '` should create clone with the same `[[Pr
ents', 1, function() { ototype]]` as `value`', function(assert) {
var argsList = [], assert.expect(1);
foo = new Foo;
func(foo, function() { assert.ok(func(new Foo) instanceof Foo);
argsList.push(slice.call(arguments)); });
});
deepEqual(argsList, isDeep ? [[foo], [1, 'a', foo]] : [[foo]]); QUnit.test('should ensure `value` constructor is a function before using i
ts `[[Prototype]]`', function(assert) {
assert.expect(1);
Foo.prototype.constructor = null;
assert.notOk(func(new Foo) instanceof Foo);
Foo.prototype.constructor = Foo;
}); });
test('`_.' + methodName + '` should support the `thisArg` argument', 1, fu QUnit.test('`_.' + methodName + '` should clone properties that shadow tho
nction() { se on `Object.prototype`', function(assert) {
var actual = func('a', function(value) { assert.expect(2);
return this[value];
}, { 'a': 'A' }); var object = {
'constructor': objectProto.constructor,
'hasOwnProperty': objectProto.hasOwnProperty,
'isPrototypeOf': objectProto.isPrototypeOf,
'propertyIsEnumerable': objectProto.propertyIsEnumerable,
'toLocaleString': objectProto.toLocaleString,
'toString': objectProto.toString,
'valueOf': objectProto.valueOf
};
var actual = func(object);
strictEqual(actual, 'A'); assert.deepEqual(actual, object);
assert.notStrictEqual(actual, object);
}); });
test('`_.' + methodName + '` should handle cloning if `customizer` returns QUnit.test('`_.' + methodName + '` should clone symbol properties', functi
`undefined`', 1, function() { on(assert) {
var actual = func({ 'a': { 'b': 'c' } }, _.noop); assert.expect(2);
deepEqual(actual, { 'a': { 'b': 'c' } });
if (Symbol) {
var object = {};
object[symbol] = {};
assert.strictEqual(func(object)[symbol], object[symbol]);
if (isDeep) {
object = { 'a': { 'b': {} } };
object.a.b[symbol] = {};
assert.strictEqual(func(object).a.b[symbol], object.a.b[symbol]);
}
else {
skipTest(assert);
}
}
else {
skipTest(assert, 2);
}
}); });
test('`_.' + methodName + '` should clone `index` and `input` array proper QUnit.test('`_.' + methodName + '` should clone symbol objects', function(
ties', 2, function() { assert) {
var array = /x/.exec('vwxyz'), assert.expect(4);
actual = func(array);
if (Symbol) {
assert.strictEqual(func(symbol), symbol);
var object = Object(symbol),
actual = func(object);
strictEqual(actual.index, 2); assert.strictEqual(typeof actual, 'object');
strictEqual(actual.input, 'vwxyz'); assert.strictEqual(typeof actual.valueOf(), 'symbol');
assert.notStrictEqual(actual, object);
}
else {
skipTest(assert, 4);
}
}); });
test('`_.' + methodName + '` should clone `lastIndex` regexp property', 1, QUnit.test('`_.' + methodName + '` should not clone symbol primitives', fu
function() { nction(assert) {
// Avoid a regexp literal for older Opera and use `exec` for older Safar assert.expect(1);
i.
var regexp = RegExp('x', 'g');
regexp.exec('vwxyz');
var actual = func(regexp); if (Symbol) {
strictEqual(actual.lastIndex, 3); assert.strictEqual(func(symbol), symbol);
}
else {
skipTest(assert);
}
}); });
test('`_.' + methodName + '` should not error on DOM elements', 1, functio QUnit.test('`_.' + methodName + '` should not error on DOM elements', func
n() { tion(assert) {
assert.expect(1);
if (document) { if (document) {
var element = document.createElement('div'); var element = document.createElement('div');
try { try {
deepEqual(func(element), {}); assert.deepEqual(func(element), {});
} catch(e) { } catch (e) {
ok(false, e.message); assert.ok(false, e.message);
} }
} }
else { else {
skipTest(); skipTest(assert);
} }
}); });
test('`_.' + methodName + '` should perform a ' + (isDeep ? 'deep' : 'shal QUnit.test('`_.' + methodName + '` should perform a ' + (isDeep ? 'deep' :
low') + ' clone when used as an iteratee for `_.map`', 3, function() { 'shallow') + ' clone when used as an iteratee for methods like `_.map`', functi
on(assert) {
assert.expect(2);
var expected = [{ 'a': [0] }, { 'b': [1] }], var expected = [{ 'a': [0] }, { 'b': [1] }],
actual = _.map(expected, func); actual = lodashStable.map(expected, func);
deepEqual(actual, expected); assert.deepEqual(actual, expected);
if (isDeep) { if (isDeep) {
ok(actual[0] !== expected[0] && actual[0].a !== expected[0].a && actua l[1].b !== expected[1].b); assert.ok(actual[0] !== expected[0] && actual[0].a !== expected[0].a & & actual[1].b !== expected[1].b);
} else { } else {
ok(actual[0] !== expected[0] && actual[0].a === expected[0].a && actua l[1].b === expected[1].b); assert.ok(actual[0] !== expected[0] && actual[0].a === expected[0].a & & actual[1].b === expected[1].b);
} }
actual = _.map(isDeep ? Object('abc') : 'abc', func);
deepEqual(actual, ['a', 'b', 'c']);
}); });
test('`_.' + methodName + '` should create an object from the same realm a QUnit.test('`_.' + methodName + '` should create an object from the same r
s `value`', 1, function() { ealm as `value`', function(assert) {
var objects = _.transform(_, function(result, value, key) { assert.expect(1);
if (_.startsWith(key, '_') && _.isObject(value) && !_.isArguments(valu
e) && !_.isElement(value) && !_.isFunction(value)) { var props = [];
var objects = lodashStable.transform(_, function(result, value, key) {
if (lodashStable.startsWith(key, '_') && lodashStable.isObject(value)
&& !lodashStable.isArguments(value) && !lodashStable.isElement(value) && !lodash
Stable.isFunction(value)) {
props.push(lodashStable.capitalize(lodashStable.camelCase(key)));
result.push(value); result.push(value);
} }
}, []); }, []);
var expected = _.times(objects.length, _.constant(true)); var expected = lodashStable.map(objects, alwaysTrue);
var actual = _.map(objects, function(object) { var actual = lodashStable.map(objects, function(object) {
var Ctor = object.constructor, var Ctor = object.constructor,
result = func(object); result = func(object);
return result !== object && (result instanceof Ctor || !(new Ctor inst anceof Ctor)); return result !== object && ((result instanceof Ctor) || !(new Ctor in stanceof Ctor));
}); });
deepEqual(actual, expected); assert.deepEqual(actual, expected, props.join(', '));
}); });
test('`_.' + methodName + '` should return a unwrapped value when chaining QUnit.test('`_.' + methodName + '` should return a unwrapped value when ch
', 2, function() { aining', function(assert) {
assert.expect(2);
if (!isNpm) { if (!isNpm) {
var object = objects['objects'], var object = objects['objects'],
actual = _(object)[methodName](); actual = _(object)[methodName]();
deepEqual(actual, object); assert.deepEqual(actual, object);
notStrictEqual(actual, object); assert.notStrictEqual(actual, object);
} }
else { else {
skipTest(2); skipTest(assert, 2);
} }
}); });
});
}(1, 2, 3));
/*--------------------------------------------------------------------------*/ lodashStable.each(typedArrays, function(type) {
QUnit.test('`_.' + methodName + '` should clone ' + type + ' arrays', fu
nction(assert) {
assert.expect(10);
QUnit.module('lodash.compact'); var Ctor = root[type];
(function() { lodashStable.times(2, function(index) {
test('should filter falsey values', 1, function() { if (Ctor) {
var array = ['0', '1', '2']; var buffer = new ArrayBuffer(24),
deepEqual(_.compact(falsey.concat(array)), array); array = index ? new Ctor(buffer, 8, 1) : new Ctor(buffer),
}); actual = func(array);
test('should return a wrapped value when chaining', 2, function() { assert.deepEqual(actual, array);
if (!isNpm) { assert.notStrictEqual(actual, array);
var wrapped = _(falsey).compact(); assert.strictEqual(actual.buffer === array.buffer, !isDeep);
ok(wrapped instanceof _); assert.strictEqual(actual.byteOffset, array.byteOffset);
deepEqual(wrapped.value(), []); assert.strictEqual(actual.length, array.length);
} }
else { else {
skipTest(2); skipTest(assert, 5);
} }
});
});
});
lodashStable.forOwn(uncloneable, function(value, key) {
QUnit.test('`_.' + methodName + '` should not clone ' + key, function(as
sert) {
assert.expect(3);
if (value) {
var object = { 'a': value, 'b': { 'c': value } },
actual = func(object),
expected = (typeof value == 'function' && !!value.c) ? { 'c': Fo
o.c } : {};
assert.deepEqual(actual, object);
assert.notStrictEqual(actual, object);
assert.deepEqual(func(value), expected);
}
else {
skipTest(assert, 3);
}
});
});
}); });
test('should work when in between lazy operators', 2, function() { lodashStable.each(['cloneWith', 'cloneDeepWith'], function(methodName) {
if (!isNpm) { var func = _[methodName],
var actual = _(falsey).slice().compact().slice().value(); isDeep = methodName == 'cloneDeepWith';
deepEqual(actual, []);
actual = _(falsey).slice().push(true, 1).compact().push('a').slice().val QUnit.test('`_.' + methodName + '` should provide the correct `customizer`
ue(); arguments', function(assert) {
deepEqual(actual, [true, 1, 'a']); assert.expect(1);
}
else {
skipTest(2);
}
});
}());
/*--------------------------------------------------------------------------*/ var argsList = [],
foo = new Foo;
QUnit.module('lodash.flowRight'); func(foo, function() {
var length = arguments.length,
args = slice.call(arguments, 0, length - (length > 1 ? 1 : 0));
(function() { argsList.push(args);
test('should be aliased', 2, function() { });
strictEqual(_.backflow, _.flowRight);
strictEqual(_.compose, _.flowRight);
});
}());
/*--------------------------------------------------------------------------*/ assert.deepEqual(argsList, isDeep ? [[foo], [1, 'a', foo]] : [[foo]]);
});
QUnit.module('flow methods'); QUnit.test('`_.' + methodName + '` should handle cloning if `customizer` r
eturns `undefined`', function(assert) {
assert.expect(1);
_.each(['flow', 'flowRight'], function(methodName, index) { var actual = func({ 'a': { 'b': 'c' } }, noop);
var func = _[methodName], assert.deepEqual(actual, { 'a': { 'b': 'c' } });
isFlow = !index; });
test('`_.' + methodName + '` should supply each function with the return val lodashStable.forOwn(uncloneable, function(value, key) {
ue of the previous', 1, function() { QUnit.test('`_.' + methodName + '` should work with a `customizer` callb
function add(x, y) { ack and ' + key, function(assert) {
return x + y; assert.expect(4);
}
function square(n) { var customizer = function(value) {
return n * n; return lodashStable.isPlainObject(value) ? undefined : value;
} };
function fixed(n) { var actual = func(value, customizer);
return n.toFixed(1);
} assert.deepEqual(actual, value);
assert.strictEqual(actual, value);
var object = { 'a': value, 'b': { 'c': value } };
actual = func(object, customizer);
var combined = isFlow ? func(add, square, fixed) : func(fixed, square, add assert.deepEqual(actual, object);
); assert.notStrictEqual(actual, object);
strictEqual(combined(1, 2), '9.0'); });
});
}); });
}(1, 2, 3));
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.compact');
(function() {
QUnit.test('should filter falsey values', function(assert) {
assert.expect(1);
test('`_.' + methodName + '` should return a new function', 1, function() { var array = ['0', '1', '2'];
notStrictEqual(func(_.noop), _.noop); assert.deepEqual(_.compact(falsey.concat(array)), array);
}); });
test('`_.' + methodName + '` should return a noop function when no arguments QUnit.test('should work when in-between lazy operators', function(assert) {
are provided', 2, function() { assert.expect(2);
var combined = func();
try { if (!isNpm) {
strictEqual(combined(), undefined); var actual = _(falsey).thru(_.slice).compact().thru(_.slice).value();
} catch(e) { assert.deepEqual(actual, []);
ok(false, e.message);
actual = _(falsey).thru(_.slice).push(true, 1).compact().push('a').value
();
assert.deepEqual(actual, [true, 1, 'a']);
}
else {
skipTest(assert, 2);
} }
notStrictEqual(combined, _.noop);
}); });
test('`_.' + methodName + '` should return a wrapped value when chaining', 1 QUnit.test('should work in a lazy sequence', function(assert) {
, function() { assert.expect(1);
if (!isNpm) { if (!isNpm) {
var wrapped = _(_.noop)[methodName](); var array = lodashStable.range(LARGE_ARRAY_SIZE).concat(null),
ok(wrapped instanceof _); actual = _(array).slice(1).compact().reverse().take().value();
assert.deepEqual(actual, _.take(_.compact(_.slice(array, 1)).reverse()))
;
} }
else { else {
skipTest(); skipTest(assert);
} }
}); });
}); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.constant'); QUnit.module('lodash.concat');
(function() { (function() {
test('should create a function that returns `value`', 1, function() { QUnit.test('should concat arrays and values', function(assert) {
var object = { 'a': 1 }, assert.expect(2);
values = Array(2).concat(empties, true, 1, 'a'),
constant = _.constant(object),
expected = _.map(values, function() { return true; });
var actual = _.map(values, function(value, index) { var array = [1],
if (index == 0) { actual = _.concat(array, 2, [3], [[4]]);
var result = constant();
} else if (index == 1) {
result = constant.call({});
} else {
result = constant(value);
}
return result === object;
});
deepEqual(actual, expected); assert.deepEqual(actual, [1, 2, 3, [4]]);
assert.deepEqual(array, [1]);
}); });
test('should work with falsey values', 1, function() { QUnit.test('should treat sparse arrays as dense', function(assert) {
var expected = _.map(falsey, function() { return true; }); assert.expect(3);
var actual = _.map(falsey, function(value, index) { var expected = [],
var constant = index ? _.constant(value) : _.constant(), actual = _.concat(Array(1), Array(1));
result = constant();
return result === value || (_.isNaN(result) && _.isNaN(value)); expected.push(undefined, undefined);
});
deepEqual(actual, expected); assert.ok('0'in actual);
assert.ok('1' in actual);
assert.deepEqual(actual, expected);
}); });
test('should return a wrapped value when chaining', 1, function() { QUnit.test('should return a new wrapped array', function(assert) {
assert.expect(2);
if (!isNpm) { if (!isNpm) {
var wrapped = _(true).constant(); var array = [1],
ok(wrapped instanceof _); wrapped = _(array).concat([2, 3]),
actual = wrapped.value();
assert.deepEqual(array, [1]);
assert.deepEqual(actual, [1, 2, 3]);
} }
else { else {
skipTest(); skipTest(assert, 2);
} }
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.countBy'); QUnit.module('lodash.cond');
(function() { (function() {
var array = [4.2, 6.1, 6.4]; QUnit.test('should create a conditional function', function(assert) {
assert.expect(3);
test('should work with an iteratee', 1, function() { var cond = _.cond([
var actual = _.countBy(array, function(num) { [lodashStable.matches({ 'a': 1 }), alwaysA],
return Math.floor(num); [lodashStable.matchesProperty('b', 1), alwaysB],
}, Math); [lodashStable.property('c'), alwaysC]
]);
deepEqual(actual, { '4': 1, '6': 2 }); assert.strictEqual(cond({ 'a': 1, 'b': 2, 'c': 3 }), 'a');
assert.strictEqual(cond({ 'a': 0, 'b': 1, 'c': 2 }), 'b');
assert.strictEqual(cond({ 'a': -1, 'b': 0, 'c': 1 }), 'c');
}); });
test('should use `_.identity` when `iteratee` is nullish', 1, function() { QUnit.test('should provide arguments to functions', function(assert) {
var array = [4, 6, 6], assert.expect(2);
values = [, null, undefined],
expected = _.map(values, _.constant({ '4': 1, '6': 2 }));
var actual = _.map(values, function(value, index) { var args1,
return index ? _.countBy(array, value) : _.countBy(array); args2,
}); expected = ['a', 'b', 'c'];
deepEqual(actual, expected);
});
test('should provide the correct `iteratee` arguments', 1, function() {
var args;
_.countBy(array, function() {
args || (args = slice.call(arguments));
});
deepEqual(args, [4.2, 0, array]); var cond = _.cond([[
}); function() { args1 || (args1 = slice.call(arguments)); return true; },
function() { args2 || (args2 = slice.call(arguments)); }
]]);
test('should support the `thisArg` argument', 1, function() { cond('a', 'b', 'c');
var actual = _.countBy(array, function(num) {
return this.floor(num);
}, Math);
deepEqual(actual, { '4': 1, '6': 2 }); assert.deepEqual(args1, expected);
assert.deepEqual(args2, expected);
}); });
test('should only add values to own, not inherited, properties', 2, function QUnit.test('should work with predicate shorthands', function(assert) {
() { assert.expect(3);
var actual = _.countBy([4.2, 6.1, 6.4], function(num) {
return Math.floor(num) > 4 ? 'hasOwnProperty' : 'constructor';
});
deepEqual(actual.constructor, 1); var cond = _.cond([
deepEqual(actual.hasOwnProperty, 2); [{ 'a': 1 }, alwaysA],
}); [['b', 1], alwaysB],
['c', alwaysC]
]);
test('should work with a "_.pluck" style `iteratee`', 1, function() { assert.strictEqual(cond({ 'a': 1, 'b': 2, 'c': 3 }), 'a');
var actual = _.countBy(['one', 'two', 'three'], 'length'); assert.strictEqual(cond({ 'a': 0, 'b': 1, 'c': 2 }), 'b');
deepEqual(actual, { '3': 2, '5': 1 }); assert.strictEqual(cond({ 'a': -1, 'b': 0, 'c': 1 }), 'c');
}); });
test('should work with a number for `iteratee`', 2, function() { QUnit.test('should return `undefined` when no condition is met', function(as
var array = [ sert) {
[1, 'a'], assert.expect(1);
[2, 'a'],
[2, 'b']
];
deepEqual(_.countBy(array, 0), { '1': 1, '2': 2 }); var cond = _.cond([[alwaysFalse, alwaysA]]);
deepEqual(_.countBy(array, 1), { 'a': 2, 'b': 1 }); assert.strictEqual(cond({ 'a': 1 }), undefined);
}); });
test('should work with an object for `collection`', 1, function() { QUnit.test('should throw a TypeError if `pairs` is not composed of functions
var actual = _.countBy({ 'a': 4.2, 'b': 6.1, 'c': 6.4 }, function(num) { ', function(assert) {
return Math.floor(num); assert.expect(2);
});
deepEqual(actual, { '4': 1, '6': 2 }); lodashStable.each([true, false], function(value) {
assert.raises(function() { _.cond([[alwaysTrue, value]])(); }, TypeError
);
});
}); });
test('should work in a lazy chain sequence', 1, function() { QUnit.test('should use `this` binding of function for `pairs`', function(ass
if (!isNpm) { ert) {
var array = [1, 2, 1, 3], assert.expect(1);
predicate = function(value) { return value > 1; },
actual = _(array).countBy(_.identity).map(String).filter(predicate).
take().value();
deepEqual(actual, ['2']); var cond = _.cond([
} [function(a) { return this[a]; }, function(a, b) { return this[b]; }]
else { ]);
skipTest();
} var object = { 'cond': cond, 'a': 1, 'b': 2 };
assert.strictEqual(object.cond('a', 'b'), 2);
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.create'); QUnit.module('lodash.conforms');
(function() { (function() {
function Shape() { var objects = [
this.x = 0; { 'a': 1, 'b': 8 },
this.y = 0; { 'a': 2, 'b': 4 },
} { 'a': 3, 'b': 16 }
];
function Circle() {
Shape.call(this);
}
test('should create an object that inherits from the given `prototype` objec
t', 3, function() {
Circle.prototype = _.create(Shape.prototype);
Circle.prototype.constructor = Circle;
var actual = new Circle; QUnit.test('should create a function that checks if a given object conforms
to `source`', function(assert) {
assert.expect(2);
ok(actual instanceof Circle); var conforms = _.conforms({
ok(actual instanceof Shape); 'b': function(value) { return value > 4; }
notStrictEqual(Circle.prototype, Shape.prototype); });
});
test('should assign `properties` to the created object', 3, function() { var actual = lodashStable.filter(objects, conforms);
var expected = { 'constructor': Circle, 'radius': 0 }; assert.deepEqual(actual, [objects[0], objects[2]]);
Circle.prototype = _.create(Shape.prototype, expected);
var actual = new Circle; conforms = _.conforms({
'b': function(value) { return value > 8; },
'a': function(value) { return value > 1; }
});
ok(actual instanceof Circle); actual = lodashStable.filter(objects, conforms);
ok(actual instanceof Shape); assert.deepEqual(actual, [objects[2]]);
deepEqual(Circle.prototype, expected);
}); });
test('should assign own properties', 1, function() { QUnit.test('should not match by inherited `source` properties', function(ass
ert) {
assert.expect(1);
function Foo() { function Foo() {
this.a = 1; this.a = function(value) {
this.c = 3; return value > 1;
};
} }
Foo.prototype.b = 2;
deepEqual(_.create({}, new Foo), { 'a': 1, 'c': 3 }); Foo.prototype.b = function(value) {
return value > 8;
};
var conforms = _.conforms(new Foo),
actual = lodashStable.filter(objects, conforms);
assert.deepEqual(actual, [objects[1], objects[2]]);
}); });
test('should accept a falsey `prototype` argument', 1, function() { QUnit.test('should not invoke `source` predicates for missing `object` prope
var expected = _.map(falsey, _.constant({})); rties', function(assert) {
assert.expect(2);
var count = 0;
var actual = _.map(falsey, function(value, index) { var conforms = _.conforms({
return index ? _.create(value) : _.create(); 'a': function() { count++; return true; }
}); });
deepEqual(actual, expected); assert.strictEqual(conforms({}), false);
assert.strictEqual(count, 0);
}); });
test('should ignore primitive `prototype` arguments and use an empty object QUnit.test('should work with a function for `object`', function(assert) {
instead', 1, function() { assert.expect(2);
var primitives = [true, null, 1, 'a', undefined],
expected = _.map(primitives, _.constant(true)); function Foo() {}
Foo.a = 1;
var actual = _.map(primitives, function(value, index) { function Bar() {}
return _.isPlainObject(index ? _.create(value) : _.create()); Bar.a = 2;
var conforms = _.conforms({
'a': function(value) { return value > 1; }
}); });
deepEqual(actual, expected); assert.strictEqual(conforms(Foo), false);
assert.strictEqual(conforms(Bar), true);
}); });
test('should work as an iteratee for `_.map`', 1, function() { QUnit.test('should work with a function for `source`', function(assert) {
var array = [{ 'a': 1 }, { 'a': 1 }, { 'a': 1 }], assert.expect(1);
expected = _.map(array, _.constant(true)),
objects = _.map(array, _.create);
var actual = _.map(objects, function(object) { function Foo() {}
return object.a === 1 && !_.keys(object).length; Foo.a = function(value) { return value > 1; };
});
deepEqual(actual, expected); var objects = [{ 'a': 1 }, { 'a': 2 }],
}); actual = lodashStable.filter(objects, _.conforms(Foo));
}());
/*--------------------------------------------------------------------------*/ assert.deepEqual(actual, [objects[1]]);
});
QUnit.module('lodash.callback'); QUnit.test('should work with a non-plain `object`', function(assert) {
assert.expect(1);
(function() { function Foo() {
test('should provide arguments to `func`', 3, function() { this.a = 1;
function fn() {
var result = [this];
push.apply(result, arguments);
return result;
} }
Foo.prototype.b = 2;
var callback = _.callback(fn), var conforms = _.conforms({
actual = callback('a', 'b', 'c', 'd', 'e', 'f'); 'b': function(value) { return value > 1; }
});
ok(actual[0] === null || actual[0] && actual[0].Array); assert.strictEqual(conforms(new Foo), true);
deepEqual(actual.slice(1), ['a', 'b', 'c', 'd', 'e', 'f']); });
var object = {}; QUnit.test('should return `false` when `object` is nullish', function(assert
callback = _.callback(fn, object); ) {
actual = callback('a', 'b'); assert.expect(1);
deepEqual(actual, [object, 'a', 'b']); var values = [, null, undefined],
}); expected = lodashStable.map(values, alwaysFalse);
test('should return `_.identity` when `func` is nullish', 1, function() { var conforms = _.conforms({
var object = {}, 'a': function(value) { return value > 1; }
values = [, null, undefined], });
expected = _.map(values, _.constant(object));
var actual = _.map(values, function(value, index) { var actual = lodashStable.map(values, function(value, index) {
var callback = index ? _.callback(value) : _.callback(); try {
return callback(object); return index ? conforms(value) : conforms();
} catch (e) {}
}); });
deepEqual(actual, expected); assert.deepEqual(actual, expected);
}); });
test('should not error when `func` is nullish and a `thisArg` is provided', QUnit.test('should return `true` when comparing an empty `source` to a nulli
2, function() { sh `object`', function(assert) {
var object = {}; assert.expect(1);
_.each([null, undefined], function(value) { var values = [, null, undefined],
expected = lodashStable.map(values, alwaysTrue),
conforms = _.conforms({});
var actual = lodashStable.map(values, function(value, index) {
try { try {
var callback = _.callback(value, {}); return index ? conforms(value) : conforms();
strictEqual(callback(object), object); } catch (e) {}
} catch(e) {
ok(false, e.message);
}
}); });
});
test('should create a callback with a falsey `thisArg`', 1, function() { assert.deepEqual(actual, expected);
var fn = function() { return this; }, });
object = {};
var expected = _.map(falsey, function(value) { QUnit.test('should return `true` when comparing an empty `source`', function
var result = fn.call(value); (assert) {
return (result && result.Array) ? object : result; assert.expect(1);
});
var actual = _.map(falsey, function(value) { var object = { 'a': 1 },
var callback = _.callback(fn, value), expected = lodashStable.map(empties, alwaysTrue);
result = callback();
return (result && result.Array) ? object : result; var actual = lodashStable.map(empties, function(value) {
var conforms = _.conforms(value);
return conforms(object);
}); });
ok(_.isEqual(actual, expected)); assert.deepEqual(actual, expected);
}); });
test('should return a callback created by `_.matches` when `func` is an obje QUnit.test('should not change behavior if `source` is modified', function(as
ct', 2, function() { sert) {
var callback = _.callback({ 'a': 1 }); assert.expect(2);
strictEqual(callback({ 'a': 1, 'b': 2 }), true);
strictEqual(callback({}), false);
});
test('should return a callback created by `_.property` when `func` is a numb var source = {
er or string', 2, function() { 'a': function(value) { return value > 1; }
var array = ['a'], };
callback = _.callback(0);
var object = { 'a': 2 },
conforms = _.conforms(source);
strictEqual(callback(array), 'a'); assert.strictEqual(conforms(object), true);
callback = _.callback('0'); source.a = function(value) { return value < 2; };
strictEqual(callback(array), 'a'); assert.strictEqual(conforms(object), true);
}); });
}());
test('should work with functions created by `_.partial` and `_.partialRight` /*--------------------------------------------------------------------------*/
', 2, function() {
function fn() {
var result = [this.a];
push.apply(result, arguments);
return result;
}
var expected = [1, 2, 3], QUnit.module('lodash.constant');
object = { 'a': 1 },
callback = _.callback(_.partial(fn, 2), object);
deepEqual(callback(3), expected); (function() {
QUnit.test('should create a function that returns `value`', function(assert)
{
assert.expect(1);
callback = _.callback(_.partialRight(fn, 3), object); var object = { 'a': 1 },
deepEqual(callback(2), expected); values = Array(2).concat(empties, true, 1, 'a'),
constant = _.constant(object),
expected = lodashStable.map(values, function() { return true; });
var actual = lodashStable.map(values, function(value, index) {
if (index == 0) {
var result = constant();
} else if (index == 1) {
result = constant.call({});
} else {
result = constant(value);
}
return result === object;
});
assert.deepEqual(actual, expected);
}); });
test('should support binding built-in methods', 2, function() { QUnit.test('should work with falsey values', function(assert) {
var object = { 'a': 1 }, assert.expect(1);
callback = _.callback(hasOwnProperty, object);
strictEqual(callback('a'), true); var expected = lodashStable.map(falsey, function() { return true; });
var fn = function() {}, var actual = lodashStable.map(falsey, function(value, index) {
bound = fn.bind && fn.bind(object); var constant = index ? _.constant(value) : _.constant(),
result = constant();
if (bound) { return (result === value) || (result !== result && value !== value);
callback = _.callback(bound, object); });
notStrictEqual(callback, bound);
}
else {
skipTest();
}
});
test('should return the function provided when there is no `this` reference' assert.deepEqual(actual, expected);
, 2, function() { });
function a() {}
function b() { return this.b; }
var object = {}; QUnit.test('should return a wrapped value when chaining', function(assert) {
assert.expect(1);
if (_.support.funcDecomp) { if (!isNpm) {
strictEqual(_.callback(a, object), a); var wrapped = _(true).constant();
notStrictEqual(_.callback(b, object), b); assert.ok(wrapped instanceof _);
} }
else { else {
skipTest(2); skipTest(assert);
} }
}); });
}());
test('should work with bizarro `_.support.funcNames`', 6, function() { /*--------------------------------------------------------------------------*/
function a() {}
var b = function() {}; QUnit.module('lodash.countBy');
function c() { (function() {
return this; var array = [4.2, 6.1, 6.4];
}
var object = {}, QUnit.test('should work with an iteratee', function(assert) {
supportBizarro = lodashBizarro ? lodashBizarro.support : {}, assert.expect(1);
funcDecomp = supportBizarro.funcDecomp,
funcNames = supportBizarro.funcNames;
supportBizarro.funcNames = !supportBizarro.funcNames;
supportBizarro.funcDecomp = true;
_.each([a, b, c], function(fn) {
if (lodashBizarro && _.support.funcDecomp) {
var callback = lodashBizarro.callback(fn, object);
strictEqual(callback(), fn === c ? object : undefined);
strictEqual(callback === fn, _.support.funcNames && fn === a);
}
else {
skipTest(2);
}
});
supportBizarro.funcDecomp = funcDecomp; var actual = _.countBy(array, function(num) {
supportBizarro.funcNames = funcNames; return Math.floor(num);
}, Math);
assert.deepEqual(actual, { '4': 1, '6': 2 });
}); });
test('should work as an iteratee for `_.map`', 1, function() { QUnit.test('should use `_.identity` when `iteratee` is nullish', function(as
var fn = function() { return this instanceof Number; }, sert) {
array = [fn, fn, fn], assert.expect(1);
expected = _.map(array, _.constant(false)),
callbacks = _.map(array, _.callback); var array = [4, 6, 6],
values = [, null, undefined],
expected = lodashStable.map(values, lodashStable.constant({ '4': 1, '6
': 2 }));
var actual = _.map(callbacks, function(callback) { var actual = lodashStable.map(values, function(value, index) {
return callback(); return index ? _.countBy(array, value) : _.countBy(array);
}); });
deepEqual(actual, expected); assert.deepEqual(actual, expected);
}); });
test('should be aliased', 1, function() { QUnit.test('should work with a "_.property" style `iteratee`', function(asse
strictEqual(_.iteratee, _.callback); rt) {
assert.expect(1);
var actual = _.countBy(['one', 'two', 'three'], 'length');
assert.deepEqual(actual, { '3': 2, '5': 1 });
}); });
}());
/*--------------------------------------------------------------------------*/ QUnit.test('should only add values to own, not inherited, properties', funct
ion(assert) {
assert.expect(2);
QUnit.module('custom `_.callback` methods'); var actual = _.countBy([4.2, 6.1, 6.4], function(num) {
return Math.floor(num) > 4 ? 'hasOwnProperty' : 'constructor';
});
(function() { assert.deepEqual(actual.constructor, 1);
var array = ['one', 'two', 'three'], assert.deepEqual(actual.hasOwnProperty, 2);
callback = _.callback, });
getPropA = _.partial(_.property, 'a'),
getPropB = _.partial(_.property, 'b'),
getLength = _.partial(_.property, 'length');
var getSum = function() { QUnit.test('should work with a number for `iteratee`', function(assert) {
return function(result, object) { assert.expect(2);
return result + object.a;
};
};
var objects = [ var array = [
{ 'a': 0, 'b': 0 }, [1, 'a'],
{ 'a': 1, 'b': 0 }, [2, 'a'],
{ 'a': 1, 'b': 1 } [2, 'b']
]; ];
test('`_.countBy` should use `_.callback` internally', 1, function() { assert.deepEqual(_.countBy(array, 0), { '1': 1, '2': 2 });
if (!isModularize) { assert.deepEqual(_.countBy(array, 1), { 'a': 2, 'b': 1 });
_.callback = getLength;
deepEqual(_.countBy(array), { '3': 2, '5': 1 });
_.callback = callback;
}
else {
skipTest();
}
}); });
test('`_.dropRightWhile` should use `_.callback` internally', 1, function() QUnit.test('should work with an object for `collection`', function(assert) {
{ assert.expect(1);
if (!isModularize) {
_.callback = getPropB;
deepEqual(_.dropRightWhile(objects), objects.slice(0, 2));
_.callback = callback;
}
else {
skipTest();
}
});
test('`_.dropWhile` should use `_.callback` internally', 1, function() { var actual = _.countBy({ 'a': 4.2, 'b': 6.1, 'c': 6.4 }, function(num) {
if (!isModularize) { return Math.floor(num);
_.callback = getPropB; });
deepEqual(_.dropWhile(objects.reverse()).reverse(), objects.reverse().sl
ice(0, 2));
_.callback = callback;
}
else {
skipTest();
}
});
test('`_.every` should use `_.callback` internally', 1, function() { assert.deepEqual(actual, { '4': 1, '6': 2 });
if (!isModularize) {
_.callback = getPropA;
strictEqual(_.every(objects.slice(1)), true);
_.callback = callback;
}
else {
skipTest();
}
}); });
test('`_.filter` should use `_.callback` internally', 1, function() { QUnit.test('should work in a lazy sequence', function(assert) {
if (!isModularize) { assert.expect(1);
var objects = [{ 'a': 0 }, { 'a': 1 }];
_.callback = getPropA; if (!isNpm) {
deepEqual(_.filter(objects), [objects[1]]); var array = lodashStable.range(LARGE_ARRAY_SIZE).concat(
_.callback = callback; lodashStable.range(Math.floor(LARGE_ARRAY_SIZE / 2), LARGE_ARRAY_SIZE)
} ,
else { lodashStable.range(Math.floor(LARGE_ARRAY_SIZE / 1.5), LARGE_ARRAY_SIZ
skipTest(); E)
} );
});
test('`_.find` should use `_.callback` internally', 1, function() { var actual = _(array).countBy().map(square).filter(isEven).take().value(
if (!isModularize) { );
_.callback = getPropA;
strictEqual(_.find(objects), objects[1]);
_.callback = callback;
}
else {
skipTest();
}
});
test('`_.findIndex` should use `_.callback` internally', 1, function() { assert.deepEqual(actual, _.take(_.filter(_.map(_.countBy(array), square)
if (!isModularize) { , isEven)));
_.callback = getPropA;
strictEqual(_.findIndex(objects), 1);
_.callback = callback;
} }
else { else {
skipTest(); skipTest(assert);
} }
}); });
}());
test('`_.findLast` should use `_.callback` internally', 1, function() { /*--------------------------------------------------------------------------*/
if (!isModularize) {
_.callback = getPropA;
strictEqual(_.findLast(objects), objects[2]);
_.callback = callback;
}
else {
skipTest();
}
});
test('`_.findLastIndex` should use `_.callback` internally', 1, function() { QUnit.module('lodash.create');
if (!isModularize) {
_.callback = getPropA;
strictEqual(_.findLastIndex(objects), 2);
_.callback = callback;
}
else {
skipTest();
}
});
test('`_.findLastKey` should use `_.callback` internally', 1, function() { (function() {
if (!isModularize) { function Shape() {
_.callback = getPropB; this.x = 0;
strictEqual(_.findKey(objects), '2'); this.y = 0;
_.callback = callback; }
}
else {
skipTest();
}
});
test('`_.findKey` should use `_.callback` internally', 1, function() { function Circle() {
if (!isModularize) { Shape.call(this);
_.callback = getPropB; }
strictEqual(_.findLastKey(objects), '2');
_.callback = callback;
}
else {
skipTest();
}
});
test('`_.groupBy` should use `_.callback` internally', 1, function() { QUnit.test('should create an object that inherits from the given `prototype`
if (!isModularize) { object', function(assert) {
_.callback = getLength; assert.expect(3);
deepEqual(_.groupBy(array), { '3': ['one', 'two'], '5': ['three'] });
_.callback = callback;
}
else {
skipTest();
}
});
test('`_.indexBy` should use `_.callback` internally', 1, function() { Circle.prototype = _.create(Shape.prototype);
if (!isModularize) { Circle.prototype.constructor = Circle;
_.callback = getLength;
deepEqual(_.indexBy(array), { '3': 'two', '5': 'three' });
_.callback = callback;
}
else {
skipTest();
}
});
test('`_.map` should use `_.callback` internally', 1, function() { var actual = new Circle;
if (!isModularize) {
_.callback = getPropA;
deepEqual(_.map(objects), [0, 1, 1]);
_.callback = callback;
}
else {
skipTest();
}
});
test('`_.mapValues` should use `_.callback` internally', 1, function() { assert.ok(actual instanceof Circle);
if (!isModularize) { assert.ok(actual instanceof Shape);
_.callback = getPropB; assert.notStrictEqual(Circle.prototype, Shape.prototype);
deepEqual(_.mapValues({ 'a': { 'b': 1 } }), { 'a': 1 });
_.callback = callback;
}
else {
skipTest();
}
}); });
test('`_.max` should use `_.callback` internally', 1, function() { QUnit.test('should assign `properties` to the created object', function(asse
if (!isModularize) { rt) {
_.callback = getPropB; assert.expect(3);
deepEqual(_.max(objects), objects[2]);
_.callback = callback;
}
else {
skipTest();
}
});
test('`_.min` should use `_.callback` internally', 1, function() { var expected = { 'constructor': Circle, 'radius': 0 };
if (!isModularize) { Circle.prototype = _.create(Shape.prototype, expected);
_.callback = getPropB;
deepEqual(_.min(objects), objects[0]);
_.callback = callback;
}
else {
skipTest();
}
});
test('`_.partition` should use `_.callback` internally', 1, function() { var actual = new Circle;
if (!isModularize) {
var objects = [{ 'a': 1 }, { 'a': 1 }, { 'b': 2 }];
_.callback = getPropA; assert.ok(actual instanceof Circle);
deepEqual(_.partition(objects), [objects.slice(0, 2), objects.slice(2)]) assert.ok(actual instanceof Shape);
; assert.deepEqual(Circle.prototype, expected);
_.callback = callback;
}
else {
skipTest();
}
}); });
test('`_.reduce` should use `_.callback` internally', 1, function() { QUnit.test('should assign own properties', function(assert) {
if (!isModularize) { assert.expect(1);
_.callback = getSum;
strictEqual(_.reduce(objects, undefined, 0), 2);
_.callback = callback;
}
else {
skipTest();
}
});
test('`_.reduceRight` should use `_.callback` internally', 1, function() { function Foo() {
if (!isModularize) { this.a = 1;
_.callback = getSum; this.c = 3;
strictEqual(_.reduceRight(objects, undefined, 0), 2);
_.callback = callback;
}
else {
skipTest();
} }
}); Foo.prototype.b = 2;
test('`_.reject` should use `_.callback` internally', 1, function() {
if (!isModularize) {
var objects = [{ 'a': 0 }, { 'a': 1 }];
_.callback = getPropA; assert.deepEqual(_.create({}, new Foo), { 'a': 1, 'c': 3 });
deepEqual(_.reject(objects), [objects[0]]);
_.callback = callback;
}
else {
skipTest();
}
}); });
test('`_.remove` should use `_.callback` internally', 1, function() { QUnit.test('should accept a falsey `prototype` argument', function(assert) {
if (!isModularize) { assert.expect(1);
var objects = [{ 'a': 0 }, { 'a': 1 }];
_.callback = getPropA; var expected = lodashStable.map(falsey, alwaysEmptyObject);
_.remove(objects);
deepEqual(objects, [{ 'a': 0 }]);
_.callback = callback;
}
else {
skipTest();
}
});
test('`_.some` should use `_.callback` internally', 1, function() { var actual = lodashStable.map(falsey, function(prototype, index) {
if (!isModularize) { return index ? _.create(prototype) : _.create();
_.callback = getPropB; });
strictEqual(_.some(objects), true);
_.callback = callback;
}
else {
skipTest();
}
});
test('`_.sortBy` should use `_.callback` internally', 1, function() { assert.deepEqual(actual, expected);
if (!isModularize) {
_.callback = getPropA;
deepEqual(_.sortBy(objects.slice().reverse()), [objects[0], objects[2],
objects[1]]);
_.callback = callback;
}
else {
skipTest();
}
}); });
test('`_.sortedIndex` should use `_.callback` internally', 1, function() { QUnit.test('should ignore primitive `prototype` arguments and use an empty o
if (!isModularize) { bject instead', function(assert) {
var objects = [{ 'a': 30 }, { 'a': 50 }]; assert.expect(1);
_.callback = getPropA;
strictEqual(_.sortedIndex(objects, { 'a': 40 }), 1);
_.callback = callback;
}
else {
skipTest();
}
});
test('`_.sortedLastIndex` should use `_.callback` internally', 1, function() var primitives = [true, null, 1, 'a', undefined],
{ expected = lodashStable.map(primitives, alwaysTrue);
if (!isModularize) {
var objects = [{ 'a': 30 }, { 'a': 50 }];
_.callback = getPropA; var actual = lodashStable.map(primitives, function(value, index) {
strictEqual(_.sortedLastIndex(objects, { 'a': 40 }), 1); return lodashStable.isPlainObject(index ? _.create(value) : _.create());
_.callback = callback; });
}
else {
skipTest();
}
});
test('`_.takeRightWhile` should use `_.callback` internally', 1, function() assert.deepEqual(actual, expected);
{
if (!isModularize) {
_.callback = getPropB;
deepEqual(_.takeRightWhile(objects), objects.slice(2));
_.callback = callback;
}
else {
skipTest();
}
}); });
test('`_.takeWhile` should use `_.callback` internally', 1, function() { QUnit.test('should work as an iteratee for methods like `_.map`', function(a
if (!isModularize) { ssert) {
_.callback = getPropB; assert.expect(1);
deepEqual(_.takeWhile(objects.reverse()), objects.reverse().slice(2));
_.callback = callback;
}
else {
skipTest();
}
});
test('`_.transform` should use `_.callback` internally', 1, function() { var array = [{ 'a': 1 }, { 'a': 1 }, { 'a': 1 }],
if (!isModularize) { expected = lodashStable.map(array, alwaysTrue),
_.callback = function() { objects = lodashStable.map(array, _.create);
return function(result, object) {
result.sum += object.a;
};
};
deepEqual(_.transform(objects, undefined, { 'sum': 0 }), { 'sum': 2 }); var actual = lodashStable.map(objects, function(object) {
_.callback = callback; return object.a === 1 && !_.keys(object).length;
} });
else {
skipTest();
}
});
test('`_.uniq` should use `_.callback` internally', 1, function() { assert.deepEqual(actual, expected);
if (!isModularize) {
_.callback = getPropB;
deepEqual(_.uniq(objects), [objects[0], objects[2]]);
_.callback = callback;
}
else {
skipTest();
}
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.curry'); QUnit.module('lodash.curry');
(function() { (function() {
function fn(a, b, c, d) { function fn(a, b, c, d) {
return slice.call(arguments); return slice.call(arguments);
} }
test('should curry based on the number of arguments provided', 3, function() QUnit.test('should curry based on the number of arguments provided', functio
{ n(assert) {
assert.expect(3);
var curried = _.curry(fn), var curried = _.curry(fn),
expected = [1, 2, 3, 4]; expected = [1, 2, 3, 4];
deepEqual(curried(1)(2)(3)(4), expected); assert.deepEqual(curried(1)(2)(3)(4), expected);
deepEqual(curried(1, 2)(3, 4), expected); assert.deepEqual(curried(1, 2)(3, 4), expected);
deepEqual(curried(1, 2, 3, 4), expected); assert.deepEqual(curried(1, 2, 3, 4), expected);
}); });
test('should allow specifying `arity`', 3, function() { QUnit.test('should allow specifying `arity`', function(assert) {
assert.expect(3);
var curried = _.curry(fn, 3), var curried = _.curry(fn, 3),
expected = [1, 2, 3]; expected = [1, 2, 3];
deepEqual(curried(1)(2, 3), expected); assert.deepEqual(curried(1)(2, 3), expected);
deepEqual(curried(1, 2)(3), expected); assert.deepEqual(curried(1, 2)(3), expected);
deepEqual(curried(1, 2, 3), expected); assert.deepEqual(curried(1, 2, 3), expected);
}); });
test('should coerce `arity` to a number', 2, function() { QUnit.test('should coerce `arity` to an integer', function(assert) {
var values = ['0', 'xyz'], assert.expect(2);
expected = _.map(values, _.constant([]));
var values = ['0', 0.6, 'xyz'],
expected = lodashStable.map(values, alwaysEmptyArray);
var actual = _.map(values, function(arity) { var actual = lodashStable.map(values, function(arity) {
return _.curry(fn, arity)(); return _.curry(fn, arity)();
}); });
deepEqual(actual, expected); assert.deepEqual(actual, expected);
deepEqual(_.curry(fn, '2')(1)(2), [1, 2]); assert.deepEqual(_.curry(fn, '2')(1)(2), [1, 2]);
}); });
test('should support placeholders', 4, function() { QUnit.test('should support placeholders', function(assert) {
assert.expect(4);
var curried = _.curry(fn), var curried = _.curry(fn),
ph = curried.placeholder; ph = curried.placeholder;
deepEqual(curried(1)(ph, 3)(ph, 4)(2), [1, 2, 3, 4]); assert.deepEqual(curried(1)(ph, 3)(ph, 4)(2), [1, 2, 3, 4]);
deepEqual(curried(ph, 2)(1)(ph, 4)(3), [1, 2, 3, 4]); assert.deepEqual(curried(ph, 2)(1)(ph, 4)(3), [1, 2, 3, 4]);
deepEqual(curried(ph, ph, 3)(ph, 2)(ph, 4)(1), [1, 2, 3, 4]); assert.deepEqual(curried(ph, ph, 3)(ph, 2)(ph, 4)(1), [1, 2, 3, 4]);
deepEqual(curried(ph, ph, ph, 4)(ph, ph, 3)(ph, 2)(1), [1, 2, 3, 4]); assert.deepEqual(curried(ph, ph, ph, 4)(ph, ph, 3)(ph, 2)(1), [1, 2, 3, 4]
);
}); });
test('should work with partialed methods', 2, function() { QUnit.test('should provide additional arguments after reaching the target ar
var curried = _.curry(fn), ity', function(assert) {
expected = [1, 2, 3, 4]; assert.expect(3);
var a = _.partial(curried, 1),
b = _.bind(a, null, 2),
c = _.partialRight(b, 4),
d = _.partialRight(b(3), 4);
deepEqual(c(3), expected);
deepEqual(d(), expected);
});
test('should provide additional arguments after reaching the target arity',
3, function() {
var curried = _.curry(fn, 3); var curried = _.curry(fn, 3);
deepEqual(curried(1)(2, 3, 4), [1, 2, 3, 4]); assert.deepEqual(curried(1)(2, 3, 4), [1, 2, 3, 4]);
deepEqual(curried(1, 2)(3, 4, 5), [1, 2, 3, 4, 5]); assert.deepEqual(curried(1, 2)(3, 4, 5), [1, 2, 3, 4, 5]);
deepEqual(curried(1, 2, 3, 4, 5, 6), [1, 2, 3, 4, 5, 6]); assert.deepEqual(curried(1, 2, 3, 4, 5, 6), [1, 2, 3, 4, 5, 6]);
}); });
test('should return a function with a `length` of `0`', 6, function() { QUnit.test('should return a function with a `length` of `0`', function(asser
_.times(2, function(index) { t) {
assert.expect(6);
lodashStable.times(2, function(index) {
var curried = index ? _.curry(fn, 4) : _.curry(fn); var curried = index ? _.curry(fn, 4) : _.curry(fn);
strictEqual(curried.length, 0); assert.strictEqual(curried.length, 0);
strictEqual(curried(1).length, 0); assert.strictEqual(curried(1).length, 0);
strictEqual(curried(1, 2).length, 0); assert.strictEqual(curried(1, 2).length, 0);
}); });
}); });
test('ensure `new curried` is an instance of `func`', 2, function() { QUnit.test('should ensure `new curried` is an instance of `func`', function(
assert) {
assert.expect(2);
var Foo = function(value) { var Foo = function(value) {
return value && object; return value && object;
}; };
var curried = _.curry(Foo), var curried = _.curry(Foo),
object = {}; object = {};
ok(new curried(false) instanceof Foo); assert.ok(new curried(false) instanceof Foo);
strictEqual(new curried(true), object); assert.strictEqual(new curried(true), object);
}); });
test('should not set a `this` binding', 9, function() { QUnit.test('should not set a `this` binding', function(assert) {
assert.expect(9);
var fn = function(a, b, c) { var fn = function(a, b, c) {
var value = this || {}; var value = this || {};
return [value[a], value[b], value[c]]; return [value[a], value[b], value[c]];
}; };
var object = { 'a': 1, 'b': 2, 'c': 3 }, var object = { 'a': 1, 'b': 2, 'c': 3 },
expected = [1, 2, 3]; expected = [1, 2, 3];
deepEqual(_.curry(_.bind(fn, object), 3)('a')('b')('c'), expected); assert.deepEqual(_.curry(_.bind(fn, object), 3)('a')('b')('c'), expected);
deepEqual(_.curry(_.bind(fn, object), 3)('a', 'b')('c'), expected); assert.deepEqual(_.curry(_.bind(fn, object), 3)('a', 'b')('c'), expected);
deepEqual(_.curry(_.bind(fn, object), 3)('a', 'b', 'c'), expected); assert.deepEqual(_.curry(_.bind(fn, object), 3)('a', 'b', 'c'), expected);
deepEqual(_.bind(_.curry(fn), object)('a')('b')('c'), Array(3)); assert.deepEqual(_.bind(_.curry(fn), object)('a')('b')('c'), Array(3));
deepEqual(_.bind(_.curry(fn), object)('a', 'b')('c'), Array(3)); assert.deepEqual(_.bind(_.curry(fn), object)('a', 'b')('c'), Array(3));
deepEqual(_.bind(_.curry(fn), object)('a', 'b', 'c'), expected); assert.deepEqual(_.bind(_.curry(fn), object)('a', 'b', 'c'), expected);
object.curried = _.curry(fn); object.curried = _.curry(fn);
deepEqual(object.curried('a')('b')('c'), Array(3)); assert.deepEqual(object.curried('a')('b')('c'), Array(3));
deepEqual(object.curried('a', 'b')('c'), Array(3)); assert.deepEqual(object.curried('a', 'b')('c'), Array(3));
deepEqual(object.curried('a', 'b', 'c'), expected); assert.deepEqual(object.curried('a', 'b', 'c'), expected);
});
QUnit.test('should work with partialed methods', function(assert) {
assert.expect(2);
var curried = _.curry(fn),
expected = [1, 2, 3, 4];
var a = _.partial(curried, 1),
b = _.bind(a, null, 2),
c = _.partialRight(b, 4),
d = _.partialRight(b(3), 4);
assert.deepEqual(c(3), expected);
assert.deepEqual(d(), expected);
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.curryRight'); QUnit.module('lodash.curryRight');
(function() { (function() {
function fn(a, b, c, d) { function fn(a, b, c, d) {
return slice.call(arguments); return slice.call(arguments);
} }
test('should curry based on the number of arguments provided', 3, function() QUnit.test('should curry based on the number of arguments provided', functio
{ n(assert) {
assert.expect(3);
var curried = _.curryRight(fn), var curried = _.curryRight(fn),
expected = [1, 2, 3, 4]; expected = [1, 2, 3, 4];
deepEqual(curried(4)(3)(2)(1), expected); assert.deepEqual(curried(4)(3)(2)(1), expected);
deepEqual(curried(3, 4)(1, 2), expected); assert.deepEqual(curried(3, 4)(1, 2), expected);
deepEqual(curried(1, 2, 3, 4), expected); assert.deepEqual(curried(1, 2, 3, 4), expected);
}); });
test('should allow specifying `arity`', 3, function() { QUnit.test('should allow specifying `arity`', function(assert) {
assert.expect(3);
var curried = _.curryRight(fn, 3), var curried = _.curryRight(fn, 3),
expected = [1, 2, 3]; expected = [1, 2, 3];
deepEqual(curried(3)(1, 2), expected); assert.deepEqual(curried(3)(1, 2), expected);
deepEqual(curried(2, 3)(1), expected); assert.deepEqual(curried(2, 3)(1), expected);
deepEqual(curried(1, 2, 3), expected); assert.deepEqual(curried(1, 2, 3), expected);
}); });
test('should work with partialed methods', 2, function() { QUnit.test('should coerce `arity` to an integer', function(assert) {
var curried = _.curryRight(fn), assert.expect(2);
expected = [1, 2, 3, 4];
var a = _.partialRight(curried, 4), var values = ['0', 0.6, 'xyz'],
b = _.partialRight(a, 3), expected = lodashStable.map(values, alwaysEmptyArray);
c = _.bind(b, null, 1),
d = _.partial(b(2), 1);
deepEqual(c(2), expected); var actual = lodashStable.map(values, function(arity) {
deepEqual(d(), expected); return _.curryRight(fn, arity)();
});
assert.deepEqual(actual, expected);
assert.deepEqual(_.curryRight(fn, '2')(1)(2), [2, 1]);
}); });
test('should support placeholders', 4, function() { QUnit.test('should support placeholders', function(assert) {
assert.expect(4);
var curried = _.curryRight(fn), var curried = _.curryRight(fn),
expected = [1, 2, 3, 4], expected = [1, 2, 3, 4],
ph = curried.placeholder; ph = curried.placeholder;
deepEqual(curried(4)(2, ph)(1, ph)(3), expected); assert.deepEqual(curried(4)(2, ph)(1, ph)(3), expected);
deepEqual(curried(3, ph)(4)(1, ph)(2), expected); assert.deepEqual(curried(3, ph)(4)(1, ph)(2), expected);
deepEqual(curried(ph, ph, 4)(ph, 3)(ph, 2)(1), expected); assert.deepEqual(curried(ph, ph, 4)(ph, 3)(ph, 2)(1), expected);
deepEqual(curried(ph, ph, ph, 4)(ph, ph, 3)(ph, 2)(1), expected); assert.deepEqual(curried(ph, ph, ph, 4)(ph, ph, 3)(ph, 2)(1), expected);
}); });
test('should provide additional arguments after reaching the target arity', QUnit.test('should provide additional arguments after reaching the target ar
3, function() { ity', function(assert) {
assert.expect(3);
var curried = _.curryRight(fn, 3); var curried = _.curryRight(fn, 3);
deepEqual(curried(4)(1, 2, 3), [1, 2, 3, 4]); assert.deepEqual(curried(4)(1, 2, 3), [1, 2, 3, 4]);
deepEqual(curried(4, 5)(1, 2, 3), [1, 2, 3, 4, 5]); assert.deepEqual(curried(4, 5)(1, 2, 3), [1, 2, 3, 4, 5]);
deepEqual(curried(1, 2, 3, 4, 5, 6), [1, 2, 3, 4, 5, 6]); assert.deepEqual(curried(1, 2, 3, 4, 5, 6), [1, 2, 3, 4, 5, 6]);
}); });
test('should return a function with a `length` of `0`', 6, function() { QUnit.test('should return a function with a `length` of `0`', function(asser
_.times(2, function(index) { t) {
assert.expect(6);
lodashStable.times(2, function(index) {
var curried = index ? _.curryRight(fn, 4) : _.curryRight(fn); var curried = index ? _.curryRight(fn, 4) : _.curryRight(fn);
strictEqual(curried.length, 0); assert.strictEqual(curried.length, 0);
strictEqual(curried(4).length, 0); assert.strictEqual(curried(4).length, 0);
strictEqual(curried(3, 4).length, 0); assert.strictEqual(curried(3, 4).length, 0);
}); });
}); });
test('ensure `new curried` is an instance of `func`', 2, function() { QUnit.test('should ensure `new curried` is an instance of `func`', function(
assert) {
assert.expect(2);
var Foo = function(value) { var Foo = function(value) {
return value && object; return value && object;
}; };
var curried = _.curryRight(Foo), var curried = _.curryRight(Foo),
object = {}; object = {};
ok(new curried(false) instanceof Foo); assert.ok(new curried(false) instanceof Foo);
strictEqual(new curried(true), object); assert.strictEqual(new curried(true), object);
}); });
test('should not set a `this` binding', 9, function() { QUnit.test('should not set a `this` binding', function(assert) {
assert.expect(9);
var fn = function(a, b, c) { var fn = function(a, b, c) {
var value = this || {}; var value = this || {};
return [value[a], value[b], value[c]]; return [value[a], value[b], value[c]];
}; };
var object = { 'a': 1, 'b': 2, 'c': 3 }, var object = { 'a': 1, 'b': 2, 'c': 3 },
expected = [1, 2, 3]; expected = [1, 2, 3];
deepEqual(_.curryRight(_.bind(fn, object), 3)('c')('b')('a'), expected); assert.deepEqual(_.curryRight(_.bind(fn, object), 3)('c')('b')('a'), expec
deepEqual(_.curryRight(_.bind(fn, object), 3)('b', 'c')('a'), expected); ted);
deepEqual(_.curryRight(_.bind(fn, object), 3)('a', 'b', 'c'), expected); assert.deepEqual(_.curryRight(_.bind(fn, object), 3)('b', 'c')('a'), expec
ted);
deepEqual(_.bind(_.curryRight(fn), object)('c')('b')('a'), Array(3)); assert.deepEqual(_.curryRight(_.bind(fn, object), 3)('a', 'b', 'c'), expec
deepEqual(_.bind(_.curryRight(fn), object)('b', 'c')('a'), Array(3)); ted);
deepEqual(_.bind(_.curryRight(fn), object)('a', 'b', 'c'), expected);
assert.deepEqual(_.bind(_.curryRight(fn), object)('c')('b')('a'), Array(3)
);
assert.deepEqual(_.bind(_.curryRight(fn), object)('b', 'c')('a'), Array(3)
);
assert.deepEqual(_.bind(_.curryRight(fn), object)('a', 'b', 'c'), expected
);
object.curried = _.curryRight(fn); object.curried = _.curryRight(fn);
deepEqual(object.curried('c')('b')('a'), Array(3)); assert.deepEqual(object.curried('c')('b')('a'), Array(3));
deepEqual(object.curried('b', 'c')('a'), Array(3)); assert.deepEqual(object.curried('b', 'c')('a'), Array(3));
deepEqual(object.curried('a', 'b', 'c'), expected); assert.deepEqual(object.curried('a', 'b', 'c'), expected);
});
QUnit.test('should work with partialed methods', function(assert) {
assert.expect(2);
var curried = _.curryRight(fn),
expected = [1, 2, 3, 4];
var a = _.partialRight(curried, 4),
b = _.partialRight(a, 3),
c = _.bind(b, null, 1),
d = _.partial(b(2), 1);
assert.deepEqual(c(2), expected);
assert.deepEqual(d(), expected);
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('curry methods'); QUnit.module('curry methods');
_.each(['curry', 'curryRight'], function(methodName) { lodashStable.each(['curry', 'curryRight'], function(methodName) {
var func = _[methodName]; var func = _[methodName],
fn = function(a, b) { return slice.call(arguments); },
isCurry = methodName == 'curry';
test('`_.' + methodName + '` should work as an iteratee for `_.map`', 1, fun QUnit.test('`_.' + methodName + '` should not error on functions with the sa
ction() { me name as lodash methods', function(assert) {
var array = [_.identity, _.identity, _.identity], assert.expect(1);
curries = _.map(array, func);
var actual = _.map(curries, function(curried, index) { function run(a, b) {
return curried(index); return a + b;
}); }
deepEqual(actual, [0, 1, 2]); var curried = func(run);
try {
var actual = curried(1)(2);
} catch (e) {}
assert.strictEqual(actual, 3);
});
QUnit.test('`_.' + methodName + '` should work as an iteratee for methods li
ke `_.map`', function(assert) {
assert.expect(2);
var array = [fn, fn, fn],
object = { 'a': fn, 'b': fn, 'c': fn };
lodashStable.each([array, object], function(collection) {
var curries = lodashStable.map(collection, func),
expected = lodashStable.map(collection, lodashStable.constant(isCurr
y ? ['a', 'b'] : ['b', 'a']));
var actual = lodashStable.map(curries, function(curried) {
return curried('a')('b');
});
assert.deepEqual(actual, expected);
});
}); });
}); });
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.debounce'); QUnit.module('lodash.debounce');
(function() { (function() {
asyncTest('should debounce a function', 2, function() { QUnit.test('should debounce a function', function(assert) {
if (!(isRhino && isModularize)) { assert.expect(2);
var count = 0,
debounced = _.debounce(function() { count++; }, 32);
debounced(); var done = assert.async();
debounced();
debounced();
strictEqual(count, 0); var callCount = 0,
debounced = _.debounce(function() { callCount++; }, 32);
setTimeout(function() { debounced();
strictEqual(count, 1); debounced();
QUnit.start(); debounced();
}, 96);
} assert.strictEqual(callCount, 0);
else {
skipTest(2); setTimeout(function() {
QUnit.start(); assert.strictEqual(callCount, 1);
} done();
}, 96);
}); });
asyncTest('subsequent debounced calls return the last `func` result', 2, fun QUnit.test('subsequent debounced calls return the last `func` result', funct
ction() { ion(assert) {
if (!(isRhino && isModularize)) { assert.expect(2);
var debounced = _.debounce(_.identity, 32);
debounced('x');
setTimeout(function() { var done = assert.async();
notEqual(debounced('y'), 'y');
}, 64);
setTimeout(function() { var debounced = _.debounce(identity, 32);
notEqual(debounced('z'), 'z'); debounced('x');
QUnit.start();
}, 128); setTimeout(function() {
} assert.notEqual(debounced('y'), 'y');
else { }, 64);
skipTest(2);
QUnit.start(); setTimeout(function() {
} assert.notEqual(debounced('z'), 'z');
done();
}, 128);
}); });
asyncTest('subsequent "immediate" debounced calls return the last `func` res QUnit.test('subsequent "immediate" debounced calls return the last `func` re
ult', 2, function() { sult', function(assert) {
if (!(isRhino && isModularize)) { assert.expect(2);
var debounced = _.debounce(_.identity, 32, true),
result = [debounced('x'), debounced('y')];
deepEqual(result, ['x', 'x']); var done = assert.async();
setTimeout(function() { var debounced = _.debounce(identity, 32, { 'leading': true, 'trailing': fa
var result = [debounced('a'), debounced('b')]; lse }),
deepEqual(result, ['a', 'a']); result = [debounced('x'), debounced('y')];
QUnit.start();
}, 64); assert.deepEqual(result, ['x', 'x']);
}
else { setTimeout(function() {
skipTest(2); var result = [debounced('a'), debounced('b')];
QUnit.start(); assert.deepEqual(result, ['a', 'a']);
} done();
}, 64);
}); });
asyncTest('should apply default options correctly', 2, function() { QUnit.test('should apply default options', function(assert) {
if (!(isRhino && isModularize)) { assert.expect(2);
var count = 0;
var debounced = _.debounce(function(value) { var done = assert.async();
count++;
return value;
}, 32, {});
strictEqual(debounced('x'), undefined); var callCount = 0;
setTimeout(function() { var debounced = _.debounce(function(value) {
strictEqual(count, 1); callCount++;
QUnit.start(); return value;
}, 64); }, 32, {});
}
else { assert.strictEqual(debounced('a'), undefined);
skipTest(2);
QUnit.start(); setTimeout(function() {
} assert.strictEqual(callCount, 1);
done();
}, 64);
}); });
asyncTest('should support a `leading` option', 7, function() { QUnit.test('should support a `leading` option', function(assert) {
if (!(isRhino && isModularize)) { assert.expect(5);
var withLeading,
counts = [0, 0, 0];
_.each([true, { 'leading': true }], function(options, index) { var done = assert.async();
var debounced = _.debounce(function(value) {
counts[index]++;
return value;
}, 32, options);
if (index == 1) { var callCounts = [0, 0];
withLeading = debounced;
}
strictEqual(debounced('x'), 'x');
});
_.each([false, { 'leading': false }], function(options) { var withLeading = _.debounce(function(value) {
var withoutLeading = _.debounce(_.identity, 32, options); callCounts[0]++;
strictEqual(withoutLeading('x'), undefined); return value;
}); }, 32, { 'leading': true });
var withLeadingAndTrailing = _.debounce(function() { assert.strictEqual(withLeading('a'), 'a');
counts[2]++;
}, 32, { 'leading': true });
withLeadingAndTrailing(); var withoutLeading = _.debounce(identity, 32, { 'leading': false });
withLeadingAndTrailing(); assert.strictEqual(withoutLeading('a'), undefined);
strictEqual(counts[2], 1); var withLeadingAndTrailing = _.debounce(function() {
callCounts[1]++;
}, 32, { 'leading': true });
setTimeout(function() { withLeadingAndTrailing();
deepEqual(counts, [1, 1, 2]); withLeadingAndTrailing();
withLeading('x'); assert.strictEqual(callCounts[1], 1);
strictEqual(counts[1], 2);
QUnit.start(); setTimeout(function() {
}, 64); assert.deepEqual(callCounts, [1, 2]);
}
else { withLeading('a');
skipTest(7); assert.strictEqual(callCounts[0], 2);
QUnit.start();
} done();
}, 64);
}); });
asyncTest('should support a `trailing` option', 4, function() { QUnit.test('should support a `trailing` option', function(assert) {
if (!(isRhino && isModularize)) { assert.expect(4);
var withCount = 0,
withoutCount = 0;
var withTrailing = _.debounce(function(value) { var done = assert.async();
withCount++;
return value;
}, 32, { 'trailing': true });
var withoutTrailing = _.debounce(function(value) { var withCount = 0,
withoutCount++; withoutCount = 0;
return value;
}, 32, { 'trailing': false });
strictEqual(withTrailing('x'), undefined); var withTrailing = _.debounce(function(value) {
strictEqual(withoutTrailing('x'), undefined); withCount++;
return value;
}, 32, { 'trailing': true });
setTimeout(function() { var withoutTrailing = _.debounce(function(value) {
strictEqual(withCount, 1); withoutCount++;
strictEqual(withoutCount, 0); return value;
QUnit.start(); }, 32, { 'trailing': false });
}, 64);
} assert.strictEqual(withTrailing('a'), undefined);
else { assert.strictEqual(withoutTrailing('a'), undefined);
skipTest(4);
QUnit.start(); setTimeout(function() {
} assert.strictEqual(withCount, 1);
assert.strictEqual(withoutCount, 0);
done();
}, 64);
}); });
asyncTest('should support a `maxWait` option', 1, function() { QUnit.test('should support a `maxWait` option', function(assert) {
if (!(isRhino && isModularize)) { assert.expect(1);
var limit = (argv || isPhantom) ? 1000 : 320,
withCount = 0,
withoutCount = 0;
var withMaxWait = _.debounce(function() { var done = assert.async();
withCount++;
}, 64, { 'maxWait': 128 });
var withoutMaxWait = _.debounce(function() { var limit = (argv || isPhantom) ? 1000 : 320,
withoutCount++; withCount = 0,
}, 96); withoutCount = 0;
var start = +new Date; var withMaxWait = _.debounce(function() {
while ((new Date - start) < limit) { withCount++;
withMaxWait(); }, 64, { 'maxWait': 128 });
withoutMaxWait();
}
var actual = [Boolean(withCount), Boolean(withoutCount)];
setTimeout(function() { var withoutMaxWait = _.debounce(function() {
deepEqual(actual, [true, false]); withoutCount++;
QUnit.start(); }, 96);
}, 1);
} var start = +new Date;
else { while ((new Date - start) < limit) {
skipTest(); withMaxWait();
QUnit.start(); withoutMaxWait();
} }
var actual = [Boolean(withCount), Boolean(withoutCount)];
setTimeout(function() {
assert.deepEqual(actual, [true, false]);
done();
}, 1);
}); });
asyncTest('should cancel `maxDelayed` when `delayed` is invoked', 1, functio QUnit.test('should cancel `maxDelayed` when `delayed` is invoked', function(
n() { assert) {
if (!(isRhino && isModularize)) { assert.expect(1);
var count = 0;
var debounced = _.debounce(function() { var done = assert.async();
count++;
}, 32, { 'maxWait': 64 });
debounced(); var callCount = 0;
setTimeout(function() { var debounced = _.debounce(function() {
strictEqual(count, 1); callCount++;
QUnit.start(); }, 32, { 'maxWait': 64 });
}, 128);
} debounced();
else {
skipTest(); setTimeout(function() {
QUnit.start(); assert.strictEqual(callCount, 1);
} done();
}, 128);
}); });
asyncTest('should invoke the `trailing` call with the correct arguments and QUnit.test('should invoke the `trailing` call with the correct arguments and
`this` binding', 2, function() { `this` binding', function(assert) {
if (!(isRhino && isModularize)) { assert.expect(2);
var actual,
count = 0,
object = {};
var debounced = _.debounce(function(value) { var done = assert.async();
actual = [this];
push.apply(actual, arguments);
return ++count != 2;
}, 32, { 'leading': true, 'maxWait': 64 });
while (true) { var actual,
if (!debounced.call(object, 'a')) { callCount = 0,
break; object = {};
}
} var debounced = _.debounce(function(value) {
setTimeout(function() { actual = [this];
strictEqual(count, 2); push.apply(actual, arguments);
deepEqual(actual, [object, 'a']); return ++callCount != 2;
QUnit.start(); }, 32, { 'leading': true, 'maxWait': 64 });
}, 64);
} while (true) {
else { if (!debounced.call(object, 'a')) {
skipTest(2); break;
QUnit.start(); }
} }
setTimeout(function() {
assert.strictEqual(callCount, 2);
assert.deepEqual(actual, [object, 'a']);
done();
}, 64);
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.deburr'); QUnit.module('lodash.deburr');
(function() { (function() {
test('should convert latin-1 supplementary letters to basic latin', 1, funct QUnit.test('should convert latin-1 supplementary letters to basic latin', fu
ion() { nction(assert) {
var actual = _.map(burredLetters, _.deburr); assert.expect(1);
deepEqual(actual, deburredLetters);
var actual = lodashStable.map(burredLetters, _.deburr);
assert.deepEqual(actual, deburredLetters);
}); });
test('should not deburr latin-1 mathematical operators', 1, function() { QUnit.test('should not deburr latin-1 mathematical operators', function(asse
rt) {
assert.expect(1);
var operators = ['\xd7', '\xf7'], var operators = ['\xd7', '\xf7'],
actual = _.map(operators, _.deburr); actual = lodashStable.map(operators, _.deburr);
deepEqual(actual, operators); assert.deepEqual(actual, operators);
});
QUnit.test('should deburr combining diacritical marks', function(assert) {
assert.expect(1);
var expected = lodashStable.map(comboMarks, lodashStable.constant('ei'));
var actual = lodashStable.map(comboMarks, function(chr) {
return _.deburr('e' + chr + 'i');
});
assert.deepEqual(actual, expected);
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.defaults'); QUnit.module('lodash.defaults');
(function() { (function() {
test('should assign properties of a source object if missing on the destinat QUnit.test('should assign source properties if missing on `object`', functio
ion object', 1, function() { n(assert) {
deepEqual(_.defaults({ 'a': 1 }, { 'a': 2, 'b': 2 }), { 'a': 1, 'b': 2 }); assert.expect(1);
assert.deepEqual(_.defaults({ 'a': 1 }, { 'a': 2, 'b': 2 }), { 'a': 1, 'b'
: 2 });
}); });
test('should accept multiple source objects', 2, function() { QUnit.test('should accept multiple sources', function(assert) {
assert.expect(2);
var expected = { 'a': 1, 'b': 2, 'c': 3 }; var expected = { 'a': 1, 'b': 2, 'c': 3 };
deepEqual(_.defaults({ 'a': 1, 'b': 2 }, { 'b': 3 }, { 'c': 3 }), expected assert.deepEqual(_.defaults({ 'a': 1, 'b': 2 }, { 'b': 3 }, { 'c': 3 }), e
); xpected);
deepEqual(_.defaults({ 'a': 1, 'b': 2 }, { 'b': 3, 'c': 3 }, { 'c': 2 }), assert.deepEqual(_.defaults({ 'a': 1, 'b': 2 }, { 'b': 3, 'c': 3 }, { 'c':
expected); 2 }), expected);
}); });
test('should not overwrite `null` values', 1, function() { QUnit.test('should not overwrite `null` values', function(assert) {
assert.expect(1);
var actual = _.defaults({ 'a': null }, { 'a': 1 }); var actual = _.defaults({ 'a': null }, { 'a': 1 });
strictEqual(actual.a, null); assert.strictEqual(actual.a, null);
}); });
test('should overwrite `undefined` values', 1, function() { QUnit.test('should overwrite `undefined` values', function(assert) {
assert.expect(1);
var actual = _.defaults({ 'a': undefined }, { 'a': 1 }); var actual = _.defaults({ 'a': undefined }, { 'a': 1 });
strictEqual(actual.a, 1); assert.strictEqual(actual.a, 1);
});
QUnit.test('should assign properties that shadow those on `Object.prototype`
', function(assert) {
assert.expect(2);
var object = {
'constructor': objectProto.constructor,
'hasOwnProperty': objectProto.hasOwnProperty,
'isPrototypeOf': objectProto.isPrototypeOf,
'propertyIsEnumerable': objectProto.propertyIsEnumerable,
'toLocaleString': objectProto.toLocaleString,
'toString': objectProto.toString,
'valueOf': objectProto.valueOf
};
var source = {
'constructor': 1,
'hasOwnProperty': 2,
'isPrototypeOf': 3,
'propertyIsEnumerable': 4,
'toLocaleString': 5,
'toString': 6,
'valueOf': 7
};
assert.deepEqual(_.defaults({}, source), source);
assert.deepEqual(_.defaults({}, object, source), object);
});
}());
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.defaultsDeep');
(function() {
QUnit.test('should deep assign source properties if missing on `object`', fu
nction(assert) {
assert.expect(1);
var object = { 'a': { 'b': 2 }, 'd': 4 },
source = { 'a': { 'b': 1, 'c': 3 }, 'e': 5 },
expected = { 'a': { 'b': 2, 'c': 3 }, 'd': 4, 'e': 5 };
assert.deepEqual(_.defaultsDeep(object, source), expected);
});
QUnit.test('should accept multiple sources', function(assert) {
assert.expect(2);
var source1 = { 'a': { 'b': 3 } },
source2 = { 'a': { 'c': 3 } },
source3 = { 'a': { 'b': 3, 'c': 3 } },
source4 = { 'a': { 'c': 4 } },
expected = { 'a': { 'b': 2, 'c': 3 } };
assert.deepEqual(_.defaultsDeep({ 'a': { 'b': 2 } }, source1, source2), ex
pected);
assert.deepEqual(_.defaultsDeep({ 'a': { 'b': 2 } }, source3, source4), ex
pected);
});
QUnit.test('should not overwrite `null` values', function(assert) {
assert.expect(1);
var object = { 'a': { 'b': null } },
source = { 'a': { 'b': 2 } },
actual = _.defaultsDeep(object, source);
assert.strictEqual(actual.a.b, null);
});
QUnit.test('should overwrite `undefined` values', function(assert) {
assert.expect(1);
var object = { 'a': { 'b': undefined } },
source = { 'a': { 'b': 2 } },
actual = _.defaultsDeep(object, source);
assert.strictEqual(actual.a.b, 2);
});
QUnit.test('should merge sources containing circular references', function(a
ssert) {
assert.expect(1);
var object = {
'foo': { 'b': { 'c': { 'd': {} } } },
'bar': { 'a': 2 }
};
var source = {
'foo': { 'b': { 'c': { 'd': {} } } },
'bar': {}
};
object.foo.b.c.d = object;
source.foo.b.c.d = source;
source.bar.b = source.foo.b;
var actual = _.defaultsDeep(object, source);
assert.ok(actual.bar.b === actual.foo.b && actual.foo.b.c.d === actual.foo
.b.c.d.foo.b.c.d);
});
QUnit.test('should not modify sources', function(assert) {
assert.expect(3);
var source1 = { 'a': 1, 'b': { 'c': 2 } },
source2 = { 'b': { 'c': 3, 'd': 3 } },
actual = _.defaultsDeep({}, source1, source2);
assert.deepEqual(actual, { 'a': 1, 'b': { 'c': 2, 'd': 3 } });
assert.deepEqual(source1, { 'a': 1, 'b': { 'c': 2 } });
assert.deepEqual(source2, { 'b': { 'c': 3, 'd': 3 } });
});
QUnit.test('should not attempt a merge of a string into an array', function(
assert) {
assert.expect(1);
var actual = _.defaultsDeep({ 'a': ['abc'] }, { 'a': 'abc' });
assert.deepEqual(actual, { 'a': ['abc'] });
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.defer'); QUnit.module('lodash.defer');
(function() { (function() {
asyncTest('should defer `func` execution', 1, function() { QUnit.test('should defer `func` execution', function(assert) {
if (!(isRhino && isModularize)) { assert.expect(1);
var pass = false;
_.defer(function() { pass = true; });
setTimeout(function() { var done = assert.async();
ok(pass);
QUnit.start(); var pass = false;
}, 128); _.defer(function() { pass = true; });
}
else { setTimeout(function() {
skipTest(); assert.ok(pass);
QUnit.start(); done();
} }, 32);
}); });
asyncTest('should accept additional arguments', 1, function() { QUnit.test('should provide additional arguments to `func`', function(assert)
if (!(isRhino && isModularize)) { {
var args; assert.expect(1);
_.defer(function() { var done = assert.async();
args = slice.call(arguments);
}, 1, 2, 3);
setTimeout(function() { var args;
deepEqual(args, [1, 2, 3]);
QUnit.start(); _.defer(function() {
}, 128); args = slice.call(arguments);
} }, 1, 2);
else {
skipTest(); setTimeout(function() {
QUnit.start(); assert.deepEqual(args, [1, 2]);
} done();
}, 32);
}); });
asyncTest('should be cancelable', 1, function() { QUnit.test('should be cancelable', function(assert) {
if (!(isRhino && isModularize)) { assert.expect(1);
var pass = true;
var timerId = _.defer(function() { var done = assert.async();
pass = false;
});
clearTimeout(timerId); var pass = true;
setTimeout(function() { var timerId = _.defer(function() {
ok(pass); pass = false;
QUnit.start(); });
}, 128);
} clearTimeout(timerId);
else {
skipTest(); setTimeout(function() {
QUnit.start(); assert.ok(pass);
} done();
}, 32);
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.delay'); QUnit.module('lodash.delay');
(function() { (function() {
asyncTest('should delay `func` execution', 2, function() { QUnit.test('should delay `func` execution', function(assert) {
if (!(isRhino && isModularize)) { assert.expect(2);
var pass = false;
_.delay(function() { pass = true; }, 96);
setTimeout(function() { var done = assert.async();
ok(!pass);
}, 32);
setTimeout(function() { var pass = false;
ok(pass); _.delay(function() { pass = true; }, 32);
QUnit.start();
}, 160); setTimeout(function() {
} assert.notOk(pass);
else { }, 1);
skipTest(2);
QUnit.start(); setTimeout(function() {
} assert.ok(pass);
done();
}, 64);
}); });
asyncTest('should accept additional arguments', 1, function() { QUnit.test('should provide additional arguments to `func`', function(assert)
if (!(isRhino && isModularize)) { {
var args; assert.expect(1);
_.delay(function() { var done = assert.async();
args = slice.call(arguments);
}, 32, 1, 2, 3);
setTimeout(function() { var args;
deepEqual(args, [1, 2, 3]);
QUnit.start(); _.delay(function() {
}, 128); args = slice.call(arguments);
} }, 32, 1, 2);
else {
skipTest(); setTimeout(function() {
QUnit.start(); assert.deepEqual(args, [1, 2]);
} done();
}, 64);
}); });
asyncTest('should be cancelable', 1, function() { QUnit.test('should use a default `wait` of `0`', function(assert) {
if (!(isRhino && isModularize)) { assert.expect(2);
var pass = true;
var timerId = _.delay(function() { var done = assert.async();
pass = false;
}, 32);
clearTimeout(timerId); var pass = false;
setTimeout(function() { _.delay(function() {
ok(pass); pass = true;
QUnit.start(); });
}, 128);
} assert.notOk(pass);
else {
skipTest(); setTimeout(function() {
QUnit.start(); assert.ok(pass);
} done();
}, 0);
});
QUnit.test('should be cancelable', function(assert) {
assert.expect(1);
var done = assert.async();
var pass = true;
var timerId = _.delay(function() {
pass = false;
}, 32);
clearTimeout(timerId);
setTimeout(function() {
assert.ok(pass);
done();
}, 64);
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.difference'); QUnit.module('difference methods');
(function() { lodashStable.each(['difference', 'differenceBy', 'differenceWith'], function(m
var args = arguments; ethodName) {
var args = (function() { return arguments; }(1, 2, 3)),
func = _[methodName];
test('should return the difference of the given arrays', 2, function() { QUnit.test('`_.' + methodName + '` should return the difference of the given
var actual = _.difference([1, 2, 3, 4, 5], [5, 2, 10]); arrays', function(assert) {
deepEqual(actual, [1, 3, 4]); assert.expect(2);
actual = _.difference([1, 2, 3, 4, 5], [5, 2, 10], [8, 4]); var actual = func([1, 2, 3, 4, 5], [5, 2, 10]);
deepEqual(actual, [1, 3]); assert.deepEqual(actual, [1, 3, 4]);
actual = func([1, 2, 3, 4, 5], [5, 2, 10], [8, 4]);
assert.deepEqual(actual, [1, 3]);
}); });
test('should match `NaN`', 1, function() { QUnit.test('`_.' + methodName + '` should match `NaN`', function(assert) {
deepEqual(_.difference([1, NaN, 3], [NaN, 5, NaN]), [1, 3]); assert.expect(1);
assert.deepEqual(func([1, NaN, 3], [NaN, 5, NaN]), [1, 3]);
}); });
test('should work with large arrays', 1, function() { QUnit.test('`_.' + methodName + '` should work with large arrays', function(
var array1 = _.range(LARGE_ARRAY_SIZE + 1), assert) {
array2 = _.range(LARGE_ARRAY_SIZE), assert.expect(1);
var array1 = lodashStable.range(LARGE_ARRAY_SIZE + 1),
array2 = lodashStable.range(LARGE_ARRAY_SIZE),
a = {}, a = {},
b = {}, b = {},
c = {}; c = {};
array1.push(a, b, c); array1.push(a, b, c);
array2.push(b, c, a); array2.push(b, c, a);
deepEqual(_.difference(array1, array2), [LARGE_ARRAY_SIZE]); assert.deepEqual(func(array1, array2), [LARGE_ARRAY_SIZE]);
}); });
test('should work with large arrays of objects', 1, function() { QUnit.test('`_.' + methodName + '` should work with large arrays of objects'
, function(assert) {
assert.expect(1);
var object1 = {}, var object1 = {},
object2 = {}, object2 = {},
largeArray = _.times(LARGE_ARRAY_SIZE, _.constant(object1)); largeArray = lodashStable.times(LARGE_ARRAY_SIZE, lodashStable.constan t(object1));
deepEqual(_.difference([object1, object2], largeArray), [object2]); assert.deepEqual(func([object1, object2], largeArray), [object2]);
}); });
test('should work with large arrays of `NaN`', 1, function() { QUnit.test('`_.' + methodName + '` should work with large arrays of `NaN`',
var largeArray = _.times(LARGE_ARRAY_SIZE, _.constant(NaN)); function(assert) {
deepEqual(_.difference([1, NaN, 3], largeArray), [1, 3]); assert.expect(1);
var largeArray = lodashStable.times(LARGE_ARRAY_SIZE, alwaysNaN);
assert.deepEqual(func([1, NaN, 3], largeArray), [1, 3]);
}); });
test('should ignore values that are not arrays or `arguments` objects', 3, f QUnit.test('`_.' + methodName + '` should ignore values that are not array-l
unction() { ike', function(assert) {
var array = [0, 1, null, 3]; assert.expect(3);
deepEqual(_.difference(array, 3, null, { '0': 1 }), array);
deepEqual(_.difference(null, array, null, [2, 1]), [0, null, 3]); var array = [1, null, 3];
deepEqual(_.difference(null, array, null, args), [0, null]); assert.deepEqual(func(args, 3, { '0': 1 }), [1, 2, 3]);
assert.deepEqual(func(null, array, 1), []);
assert.deepEqual(func(array, args, null), [null]);
}); });
}(1, 2, 3)); });
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.differenceBy');
(function() {
QUnit.test('should accept an `iteratee` argument', function(assert) {
assert.expect(2);
var actual = _.differenceBy([3.1, 2.2, 1.3], [4.4, 2.5], Math.floor);
assert.deepEqual(actual, [3.1, 1.3]);
actual = _.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x');
assert.deepEqual(actual, [{ 'x': 2 }]);
});
QUnit.test('should provide the correct `iteratee` arguments', function(asser
t) {
assert.expect(1);
var args;
_.differenceBy([3.1, 2.2, 1.3], [4.4, 2.5], function() {
args || (args = slice.call(arguments));
});
assert.deepEqual(args, [4.4]);
});
}());
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.differenceWith');
(function() {
var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
QUnit.test('should work with a `comparator` argument', function(assert) {
assert.expect(1);
var actual = _.differenceWith(objects, [{ 'x': 1, 'y': 2 }], lodashStable.
isEqual);
assert.deepEqual(actual, [{ 'x': 2, 'y': 1 }]);
});
}());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.drop'); QUnit.module('lodash.drop');
(function() { (function() {
var array = [1, 2, 3]; var array = [1, 2, 3];
test('should drop the first two elements', 1, function() { QUnit.test('should drop the first two elements', function(assert) {
deepEqual(_.drop(array, 2), [3]); assert.expect(1);
assert.deepEqual(_.drop(array, 2), [3]);
}); });
test('should treat falsey `n` values, except nullish, as `0`', 1, function() QUnit.test('should treat falsey `n` values, except `undefined`, as `0`', fun
{ ction(assert) {
var expected = _.map(falsey, function(value) { assert.expect(1);
return value == null ? [2, 3] : array;
var expected = lodashStable.map(falsey, function(value) {
return value === undefined ? [2, 3] : array;
}); });
var actual = _.map(falsey, function(n) { var actual = lodashStable.map(falsey, function(n) {
return _.drop(array, n); return _.drop(array, n);
}); });
deepEqual(actual, expected); assert.deepEqual(actual, expected);
}); });
test('should return all elements when `n` < `1`', 3, function() { QUnit.test('should return all elements when `n` < `1`', function(assert) {
_.each([0, -1, -Infinity], function(n) { assert.expect(3);
deepEqual(_.drop(array, n), array);
lodashStable.each([0, -1, -Infinity], function(n) {
assert.deepEqual(_.drop(array, n), array);
}); });
}); });
test('should return an empty array when `n` >= `array.length`', 4, function( QUnit.test('should return an empty array when `n` >= `array.length`', functi
) { on(assert) {
_.each([3, 4, Math.pow(2, 32), Infinity], function(n) { assert.expect(4);
deepEqual(_.drop(array, n), []);
lodashStable.each([3, 4, Math.pow(2, 32), Infinity], function(n) {
assert.deepEqual(_.drop(array, n), []);
}); });
}); });
test('should work as an iteratee for `_.map`', 1, function() { QUnit.test('should coerce `n` to an integer', function(assert) {
var array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]], assert.expect(1);
actual = _.map(array, _.drop);
deepEqual(actual, [[2, 3], [5, 6], [8, 9]]); assert.deepEqual(_.drop(array, 1.6), [2, 3]);
}); });
test('should return a wrapped value when chaining', 2, function() { QUnit.test('should work as an iteratee for methods like `_.map`', function(a
if (!isNpm) { ssert) {
var wrapped = _(array).drop(2); assert.expect(1);
ok(wrapped instanceof _);
deepEqual(wrapped.value(), [3]); var array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]],
} actual = lodashStable.map(array, _.drop);
else {
skipTest(2); assert.deepEqual(actual, [[2, 3], [5, 6], [8, 9]]);
}
}); });
test('should work in a lazy chain sequence', 4, function() { QUnit.test('should work in a lazy sequence', function(assert) {
assert.expect(6);
if (!isNpm) { if (!isNpm) {
var array = [1, 2, 3, 4, 5, 6, 7, 8], var array = lodashStable.range(1, LARGE_ARRAY_SIZE + 1),
predicate = function(value) { return value > 1; }, predicate = function(value) { values.push(value); return isEven(valu
e); },
values = [],
actual = _(array).drop(2).drop().value(); actual = _(array).drop(2).drop().value();
deepEqual(actual, [4, 5, 6, 7, 8]); assert.deepEqual(actual, array.slice(3));
actual = _(array).filter(predicate).drop(2).drop().value(); actual = _(array).filter(predicate).drop(2).drop().value();
deepEqual(actual, [5, 6, 7, 8]); assert.deepEqual(values, array);
assert.deepEqual(actual, _.drop(_.drop(_.filter(array, predicate), 2)));
actual = _(array).drop(2).dropRight().drop().dropRight(2).value(); actual = _(array).drop(2).dropRight().drop().dropRight(2).value();
deepEqual(actual, [4, 5]); assert.deepEqual(actual, _.dropRight(_.drop(_.dropRight(_.drop(array, 2) )), 2));
actual = _(array).filter(predicate).drop(2).dropRight().drop().dropRight values = [];
(2).value();
deepEqual(actual, [5]); actual = _(array).drop().filter(predicate).drop(2).dropRight().drop().dr
opRight(2).value();
assert.deepEqual(values, array.slice(1));
assert.deepEqual(actual, _.dropRight(_.drop(_.dropRight(_.drop(_.filter(
_.drop(array), predicate), 2))), 2));
} }
else { else {
skipTest(4); skipTest(assert, 6);
} }
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.dropRight'); QUnit.module('lodash.dropRight');
(function() { (function() {
var array = [1, 2, 3]; var array = [1, 2, 3];
test('should drop the last two elements', 1, function() { QUnit.test('should drop the last two elements', function(assert) {
deepEqual(_.dropRight(array, 2), [1]); assert.expect(1);
assert.deepEqual(_.dropRight(array, 2), [1]);
}); });
test('should treat falsey `n` values, except nullish, as `0`', 1, function() QUnit.test('should treat falsey `n` values, except `undefined`, as `0`', fun
{ ction(assert) {
var expected = _.map(falsey, function(value) { assert.expect(1);
return value == null ? [1, 2] : array;
var expected = lodashStable.map(falsey, function(value) {
return value === undefined ? [1, 2] : array;
}); });
var actual = _.map(falsey, function(n) { var actual = lodashStable.map(falsey, function(n) {
return _.dropRight(array, n); return _.dropRight(array, n);
}); });
deepEqual(actual, expected); assert.deepEqual(actual, expected);
}); });
test('should return all elements when `n` < `1`', 3, function() { QUnit.test('should return all elements when `n` < `1`', function(assert) {
_.each([0, -1, -Infinity], function(n) { assert.expect(3);
deepEqual(_.dropRight(array, n), array);
lodashStable.each([0, -1, -Infinity], function(n) {
assert.deepEqual(_.dropRight(array, n), array);
}); });
}); });
test('should return an empty array when `n` >= `array.length`', 4, function( QUnit.test('should return an empty array when `n` >= `array.length`', functi
) { on(assert) {
_.each([3, 4, Math.pow(2, 32), Infinity], function(n) { assert.expect(4);
deepEqual(_.dropRight(array, n), []);
lodashStable.each([3, 4, Math.pow(2, 32), Infinity], function(n) {
assert.deepEqual(_.dropRight(array, n), []);
}); });
}); });
test('should work as an iteratee for `_.map`', 1, function() { QUnit.test('should coerce `n` to an integer', function(assert) {
var array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]], assert.expect(1);
actual = _.map(array, _.dropRight);
deepEqual(actual, [[1, 2], [4, 5], [7, 8]]); assert.deepEqual(_.dropRight(array, 1.6), [1, 2]);
}); });
test('should return a wrapped value when chaining', 2, function() { QUnit.test('should work as an iteratee for methods like `_.map`', function(a
if (!isNpm) { ssert) {
var wrapped = _(array).dropRight(2); assert.expect(1);
ok(wrapped instanceof _);
deepEqual(wrapped.value(), [1]); var array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]],
} actual = lodashStable.map(array, _.dropRight);
else {
skipTest(2); assert.deepEqual(actual, [[1, 2], [4, 5], [7, 8]]);
}
}); });
test('should work in a lazy chain sequence', 4, function() { QUnit.test('should work in a lazy sequence', function(assert) {
assert.expect(6);
if (!isNpm) { if (!isNpm) {
var array = [1, 2, 3, 4, 5, 6, 7, 8], var array = lodashStable.range(1, LARGE_ARRAY_SIZE + 1),
predicate = function(value) { return value < 8; }, predicate = function(value) { values.push(value); return isEven(valu
e); },
values = [],
actual = _(array).dropRight(2).dropRight().value(); actual = _(array).dropRight(2).dropRight().value();
deepEqual(actual, [1, 2, 3, 4, 5]); assert.deepEqual(actual, array.slice(0, -3));
actual = _(array).filter(predicate).dropRight(2).dropRight().value(); actual = _(array).filter(predicate).dropRight(2).dropRight().value();
deepEqual(actual, [1, 2, 3, 4]); assert.deepEqual(values, array);
assert.deepEqual(actual, _.dropRight(_.dropRight(_.filter(array, predica
te), 2)));
actual = _(array).dropRight(2).drop().dropRight().drop(2).value(); actual = _(array).dropRight(2).drop().dropRight().drop(2).value();
deepEqual(actual, [4, 5]); assert.deepEqual(actual, _.drop(_.dropRight(_.drop(_.dropRight(array, 2) )), 2));
actual = _(array).filter(predicate).dropRight(2).drop().dropRight().drop values = [];
(2).value();
deepEqual(actual, [4]); actual = _(array).dropRight().filter(predicate).dropRight(2).drop().drop
Right().drop(2).value();
assert.deepEqual(values, array.slice(0, -1));
assert.deepEqual(actual, _.drop(_.dropRight(_.drop(_.dropRight(_.filter(
_.dropRight(array), predicate), 2))), 2));
} }
else { else {
skipTest(4); skipTest(assert, 6);
} }
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.dropRightWhile'); QUnit.module('lodash.dropRightWhile');
(function() { (function() {
var array = [1, 2, 3]; var array = [1, 2, 3, 4];
var objects = [ var objects = [
{ 'a': 0, 'b': 0 }, { 'a': 0, 'b': 0 },
{ 'a': 1, 'b': 1 }, { 'a': 1, 'b': 1 },
{ 'a': 2, 'b': 2 } { 'a': 2, 'b': 2 }
]; ];
test('should drop elements while `predicate` returns truthy', 1, function() QUnit.test('should drop elements while `predicate` returns truthy', function
{ (assert) {
assert.expect(1);
var actual = _.dropRightWhile(array, function(num) { var actual = _.dropRightWhile(array, function(num) {
return num > 1; return num > 2;
}); });
deepEqual(actual, [1]); assert.deepEqual(actual, [1, 2]);
}); });
test('should provide the correct `predicate` arguments', 1, function() { QUnit.test('should provide the correct `predicate` arguments', function(asse
rt) {
assert.expect(1);
var args; var args;
_.dropRightWhile(array, function() { _.dropRightWhile(array, function() {
args = slice.call(arguments); args = slice.call(arguments);
}); });
deepEqual(args, [3, 2, array]); assert.deepEqual(args, [4, 3, array]);
}); });
test('should support the `thisArg` argument', 1, function() { QUnit.test('should work with a "_.matches" style `predicate`', function(asse
var actual = _.dropRightWhile(array, function(num, index) { rt) {
return this[index] > 1; assert.expect(1);
}, array);
deepEqual(actual, [1]); assert.deepEqual(_.dropRightWhile(objects, { 'b': 2 }), objects.slice(0, 2 ));
}); });
test('should work with a "_.pluck" style `predicate`', 1, function() { QUnit.test('should work with a "_.matchesProperty" style `predicate`', funct
deepEqual(_.dropRightWhile(objects, 'b'), objects.slice(0, 1)); ion(assert) {
assert.expect(1);
assert.deepEqual(_.dropRightWhile(objects, ['b', 2]), objects.slice(0, 2))
;
}); });
test('should work with a "_.where" style `predicate`', 1, function() { QUnit.test('should work with a "_.property" style `predicate`', function(ass
deepEqual(_.dropRightWhile(objects, { 'b': 2 }), objects.slice(0, 2)); ert) {
assert.expect(1);
assert.deepEqual(_.dropRightWhile(objects, 'b'), objects.slice(0, 1));
}); });
test('should return a wrapped value when chaining', 2, function() { QUnit.test('should return a wrapped value when chaining', function(assert) {
assert.expect(2);
if (!isNpm) { if (!isNpm) {
var wrapped = _(array).dropRightWhile(function(num) { var wrapped = _(array).dropRightWhile(function(num) {
return num > 1; return num > 2;
}); });
ok(wrapped instanceof _); assert.ok(wrapped instanceof _);
deepEqual(wrapped.value(), [1]); assert.deepEqual(wrapped.value(), [1, 2]);
} }
else { else {
skipTest(2); skipTest(assert, 2);
} }
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.dropWhile'); QUnit.module('lodash.dropWhile');
(function() { (function() {
var array = [1, 2, 3]; var array = [1, 2, 3, 4];
var objects = [ var objects = [
{ 'a': 2, 'b': 2 }, { 'a': 2, 'b': 2 },
{ 'a': 1, 'b': 1 }, { 'a': 1, 'b': 1 },
{ 'a': 0, 'b': 0 } { 'a': 0, 'b': 0 }
]; ];
test('should drop elements while `predicate` returns truthy', 1, function() QUnit.test('should drop elements while `predicate` returns truthy', function
{ (assert) {
assert.expect(1);
var actual = _.dropWhile(array, function(num) { var actual = _.dropWhile(array, function(num) {
return num < 3; return num < 3;
}); });
deepEqual(actual, [3]); assert.deepEqual(actual, [3, 4]);
}); });
test('should provide the correct `predicate` arguments', 1, function() { QUnit.test('should provide the correct `predicate` arguments', function(asse
rt) {
assert.expect(1);
var args; var args;
_.dropWhile(array, function() { _.dropWhile(array, function() {
args = slice.call(arguments); args = slice.call(arguments);
}); });
deepEqual(args, [1, 0, array]); assert.deepEqual(args, [1, 0, array]);
}); });
test('should support the `thisArg` argument', 1, function() { QUnit.test('should work with a "_.matches" style `predicate`', function(asse
var actual = _.dropWhile(array, function(num, index) { rt) {
return this[index] < 3; assert.expect(1);
}, array);
deepEqual(actual, [3]); assert.deepEqual(_.dropWhile(objects, { 'b': 2 }), objects.slice(1));
}); });
test('should work with a "_.pluck" style `predicate`', 1, function() { QUnit.test('should work with a "_.matchesProperty" style `predicate`', funct
deepEqual(_.dropWhile(objects, 'b'), objects.slice(2)); ion(assert) {
assert.expect(1);
assert.deepEqual(_.dropWhile(objects, ['b', 2]), objects.slice(1));
}); });
test('should work with a "_.where" style `predicate`', 1, function() { QUnit.test('should work with a "_.property" style `predicate`', function(ass
deepEqual(_.dropWhile(objects, { 'b': 2 }), objects.slice(1)); ert) {
assert.expect(1);
assert.deepEqual(_.dropWhile(objects, 'b'), objects.slice(2));
}); });
test('should return a wrapped value when chaining', 2, function() { QUnit.test('should work in a lazy sequence', function(assert) {
assert.expect(3);
if (!isNpm) { if (!isNpm) {
var wrapped = _(array).dropWhile(function(num) { var array = lodashStable.range(1, LARGE_ARRAY_SIZE + 3),
return num < 3; predicate = function(num) { return num < 3; },
}); expected = _.dropWhile(array, predicate),
wrapped = _(array).dropWhile(predicate);
assert.deepEqual(wrapped.value(), expected);
assert.deepEqual(wrapped.reverse().value(), expected.slice().reverse());
assert.strictEqual(wrapped.last(), _.last(expected));
}
else {
skipTest(assert, 3);
}
});
QUnit.test('should work in a lazy sequence with `drop`', function(assert) {
assert.expect(1);
if (!isNpm) {
var array = lodashStable.range(1, LARGE_ARRAY_SIZE + 3);
var actual = _(array)
.dropWhile(function(num) { return num == 1; })
.drop()
.dropWhile(function(num) { return num == 3; })
.value();
ok(wrapped instanceof _); assert.deepEqual(actual, array.slice(3));
deepEqual(wrapped.value(), [3]);
} }
else { else {
skipTest(2); skipTest(assert);
} }
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.endsWith'); QUnit.module('lodash.endsWith');
(function() { (function() {
var string = 'abc'; var string = 'abc';
test('should return `true` if a string ends with `target`', 1, function() { QUnit.test('should return `true` if a string ends with `target`', function(a
strictEqual(_.endsWith(string, 'c'), true); ssert) {
assert.expect(1);
assert.strictEqual(_.endsWith(string, 'c'), true);
}); });
test('should return `false` if a string does not end with `target`', 1, func QUnit.test('should return `false` if a string does not end with `target`', f
tion() { unction(assert) {
strictEqual(_.endsWith(string, 'b'), false); assert.expect(1);
assert.strictEqual(_.endsWith(string, 'b'), false);
}); });
test('should work with a `position` argument', 1, function() { QUnit.test('should work with a `position` argument', function(assert) {
strictEqual(_.endsWith(string, 'b', 2), true); assert.expect(1);
assert.strictEqual(_.endsWith(string, 'b', 2), true);
}); });
test('should work with `position` >= `string.length`', 4, function() { QUnit.test('should work with `position` >= `string.length`', function(assert
_.each([3, 5, MAX_SAFE_INTEGER, Infinity], function(position) { ) {
strictEqual(_.endsWith(string, 'c', position), true); assert.expect(4);
lodashStable.each([3, 5, MAX_SAFE_INTEGER, Infinity], function(position) {
assert.strictEqual(_.endsWith(string, 'c', position), true);
}); });
}); });
test('should treat falsey `position` values, except `undefined`, as `0`', 1, QUnit.test('should treat falsey `position` values, except `undefined`, as `0
function() { `', function(assert) {
var expected = _.map(falsey, _.constant(true)); assert.expect(1);
var actual = _.map(falsey, function(position) { var expected = lodashStable.map(falsey, alwaysTrue);
var actual = lodashStable.map(falsey, function(position) {
return _.endsWith(string, position === undefined ? 'c' : '', position); return _.endsWith(string, position === undefined ? 'c' : '', position);
}); });
deepEqual(actual, expected); assert.deepEqual(actual, expected);
}); });
test('should treat a negative `position` as `0`', 6, function() { QUnit.test('should treat a negative `position` as `0`', function(assert) {
_.each([-1, -3, -Infinity], function(position) { assert.expect(6);
ok(_.every(string, function(chr) {
lodashStable.each([-1, -3, -Infinity], function(position) {
assert.ok(lodashStable.every(string, function(chr) {
return _.endsWith(string, chr, position) === false; return _.endsWith(string, chr, position) === false;
})); }));
strictEqual(_.endsWith(string, '', position), true); assert.strictEqual(_.endsWith(string, '', position), true);
}); });
}); });
test('should return `true` when `target` is an empty string regardless of `p QUnit.test('should coerce `position` to an integer', function(assert) {
osition`', 1, function() { assert.expect(1);
ok(_.every([-Infinity, NaN, -3, -1, 0, 1, 2, 3, 5, MAX_SAFE_INTEGER, Infin
ity], function(position) { assert.strictEqual(_.endsWith(string, 'ab', 2.2), true);
});
QUnit.test('should return `true` when `target` is an empty string regardless
of `position`', function(assert) {
assert.expect(1);
assert.ok(lodashStable.every([-Infinity, NaN, -3, -1, 0, 1, 2, 3, 5, MAX_S
AFE_INTEGER, Infinity], function(position) {
return _.endsWith(string, '', position, true); return _.endsWith(string, '', position, true);
})); }));
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.eq');
(function() {
QUnit.test('should perform a `SameValueZero` comparison of two values', func
tion(assert) {
assert.expect(11);
assert.strictEqual(_.eq(), true);
assert.strictEqual(_.eq(undefined), true);
assert.strictEqual(_.eq(0, -0), true);
assert.strictEqual(_.eq(NaN, NaN), true);
assert.strictEqual(_.eq(1, 1), true);
assert.strictEqual(_.eq(null, undefined), false);
assert.strictEqual(_.eq(1, Object(1)), false);
assert.strictEqual(_.eq(1, '1'), false);
assert.strictEqual(_.eq(1, '1'), false);
var object = { 'a': 1 };
assert.strictEqual(_.eq(object, object), true);
assert.strictEqual(_.eq(object, { 'a': 1 }), false);
});
}());
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.escape'); QUnit.module('lodash.escape');
(function() { (function() {
var escaped = '&amp;&lt;&gt;&quot;&#39;&#96;\/', var escaped = '&amp;&lt;&gt;&quot;&#39;&#96;\/',
unescaped = '&<>"\'`\/'; unescaped = '&<>"\'`\/';
escaped += escaped; escaped += escaped;
unescaped += unescaped; unescaped += unescaped;
test('should escape values', 1, function() { QUnit.test('should escape values', function(assert) {
strictEqual(_.escape(unescaped), escaped); assert.expect(1);
assert.strictEqual(_.escape(unescaped), escaped);
}); });
test('should not escape the "/" character', 1, function() { QUnit.test('should not escape the "/" character', function(assert) {
strictEqual(_.escape('/'), '/'); assert.expect(1);
assert.strictEqual(_.escape('/'), '/');
}); });
test('should handle strings with nothing to escape', 1, function() { QUnit.test('should handle strings with nothing to escape', function(assert)
strictEqual(_.escape('abc'), 'abc'); {
assert.expect(1);
assert.strictEqual(_.escape('abc'), 'abc');
}); });
test('should escape the same characters unescaped by `_.unescape`', 1, funct QUnit.test('should escape the same characters unescaped by `_.unescape`', fu
ion() { nction(assert) {
strictEqual(_.escape(_.unescape(escaped)), escaped); assert.expect(1);
assert.strictEqual(_.escape(_.unescape(escaped)), escaped);
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.escapeRegExp'); QUnit.module('lodash.escapeRegExp');
(function() { (function() {
var escaped = '\\.\\*\\+\\?\\^\\$\\{\\}\\(\\)\\|\\[\\]\\/\\\\', var escaped = '\\^\\$\\.\\*\\+\\?\\(\\)\\[\\]\\{\\}\\|\\\\',
unescaped = '.*+?^${}()|[\]\/\\'; unescaped = '^$.*+?()[]{}|\\';
escaped += escaped; QUnit.test('should escape values', function(assert) {
unescaped += unescaped; assert.expect(1);
assert.strictEqual(_.escapeRegExp(unescaped + unescaped), escaped + escape
d);
});
QUnit.test('should handle strings with nothing to escape', function(assert)
{
assert.expect(1);
test('should escape values', 1, function() { assert.strictEqual(_.escapeRegExp('ghi'), 'ghi');
strictEqual(_.escapeRegExp(unescaped), escaped);
}); });
test('should handle strings with nothing to escape', 1, function() { QUnit.test('should return an empty string for empty values', function(assert
strictEqual(_.escapeRegExp('abc'), 'abc'); ) {
assert.expect(1);
var values = [, null, undefined, ''],
expected = lodashStable.map(values, alwaysEmptyString);
var actual = lodashStable.map(values, function(value, index) {
return index ? _.escapeRegExp(value) : _.escapeRegExp();
});
assert.deepEqual(actual, expected);
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.every'); QUnit.module('lodash.every');
(function() { (function() {
test('should return `true` for empty collections', 1, function() { QUnit.test('should return `true` if `predicate` returns truthy for all eleme
var expected = _.map(empties, _.constant(true)); nts', function(assert) {
assert.expect(1);
assert.strictEqual(lodashStable.every([true, 1, 'a'], identity), true);
});
QUnit.test('should return `true` for empty collections', function(assert) {
assert.expect(1);
var expected = lodashStable.map(empties, alwaysTrue);
var actual = _.map(empties, function(value) { var actual = lodashStable.map(empties, function(value) {
try { try {
return _.every(value, _.identity); return _.every(value, identity);
} catch(e) {} } catch (e) {}
}); });
deepEqual(actual, expected); assert.deepEqual(actual, expected);
}); });
test('should return `true` if `predicate` returns truthy for all elements in QUnit.test('should return `false` as soon as `predicate` returns falsey', fu
the collection', 1, function() { nction(assert) {
strictEqual(_.every([true, 1, 'a'], _.identity), true); assert.expect(2);
});
test('should return `false` as soon as `predicate` returns falsey', 1, funct var count = 0;
ion() {
strictEqual(_.every([true, null, true], _.identity), false);
});
test('should work with collections of `undefined` values (test in IE < 9)', assert.strictEqual(_.every([true, null, true], function(value) {
1, function() { count++;
strictEqual(_.every([undefined, undefined, undefined], _.identity), false) return value;
; }), false);
});
test('should work with a "_.pluck" style `predicate`', 2, function() { assert.strictEqual(count, 2);
var objects = [{ 'a': 0, 'b': 1 }, { 'a': 1, 'b': 2 }];
strictEqual(_.every(objects, 'a'), false);
strictEqual(_.every(objects, 'b'), true);
}); });
test('should work with a "_where" style `predicate`', 2, function() { QUnit.test('should work with collections of `undefined` values (test in IE <
var objects = [{ 'a': 0, 'b': 0 }, { 'a': 0, 'b': 1 }]; 9)', function(assert) {
strictEqual(_.every(objects, { 'a': 0 }), true); assert.expect(1);
strictEqual(_.every(objects, { 'b': 1 }), false);
assert.strictEqual(_.every([undefined, undefined, undefined], identity), f
alse);
}); });
test('should use `_.identity` when `predicate` is nullish', 2, function() { QUnit.test('should use `_.identity` when `predicate` is nullish', function(a
ssert) {
assert.expect(2);
var values = [, null, undefined], var values = [, null, undefined],
expected = _.map(values, _.constant(false)); expected = lodashStable.map(values, alwaysFalse);
var actual = _.map(values, function(value, index) { var actual = lodashStable.map(values, function(value, index) {
var array = [0]; var array = [0];
return index ? _.every(array, value) : _.every(array); return index ? _.every(array, value) : _.every(array);
}); });
deepEqual(actual, expected); assert.deepEqual(actual, expected);
expected = _.map(values, _.constant(true)); expected = lodashStable.map(values, alwaysTrue);
actual = _.map(values, function(value, index) { actual = lodashStable.map(values, function(value, index) {
var array = [1]; var array = [1];
return index ? _.every(array, value) : _.every(array); return index ? _.every(array, value) : _.every(array);
}); });
deepEqual(actual, expected); assert.deepEqual(actual, expected);
});
QUnit.test('should work with a "_.property" style `predicate`', function(ass
ert) {
assert.expect(2);
var objects = [{ 'a': 0, 'b': 1 }, { 'a': 1, 'b': 2 }];
assert.strictEqual(_.every(objects, 'a'), false);
assert.strictEqual(_.every(objects, 'b'), true);
});
QUnit.test('should work with a "_.matches" style `predicate`', function(asse
rt) {
assert.expect(2);
var objects = [{ 'a': 0, 'b': 0 }, { 'a': 0, 'b': 1 }];
assert.strictEqual(_.every(objects, { 'a': 0 }), true);
assert.strictEqual(_.every(objects, { 'b': 1 }), false);
}); });
test('should be aliased', 1, function() { QUnit.test('should work as an iteratee for methods like `_.map`', function(a
strictEqual(_.all, _.every); ssert) {
assert.expect(1);
var actual = lodashStable.map([[1]], _.every);
assert.deepEqual(actual, [true]);
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('strict mode checks'); QUnit.module('strict mode checks');
_.each(['assign', 'bindAll', 'defaults'], function(methodName) { lodashStable.each(['assign', 'assignIn', 'bindAll', 'defaults'], function(meth
var func = _[methodName]; odName) {
var func = _[methodName],
isBindAll = methodName == 'bindAll';
QUnit.test('`_.' + methodName + '` should ' + (isStrict ? '' : 'not ') + 'th
row strict mode errors', function(assert) {
assert.expect(1);
test('`_.' + methodName + '` should ' + (isStrict ? '' : 'not ') + 'throw st rict mode errors', 1, function() {
if (freeze) { if (freeze) {
var object = { 'a': undefined, 'b': function() {} }, var object = freeze({ 'a': undefined, 'b': function() {} }),
pass = !isStrict; pass = !isStrict;
freeze(object);
try { try {
if (methodName == 'bindAll') { func(object, isBindAll ? 'b' : { 'a': 1 });
func(object); } catch (e) {
} else {
func(object, { 'a': 1 });
}
} catch(e) {
pass = !pass; pass = !pass;
} }
ok(pass); assert.ok(pass);
} }
else { else {
skipTest(); skipTest(assert);
} }
}); });
}); });
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.filter'); QUnit.module('lodash.fill');
(function() { (function() {
test('should return elements `predicate` returns truthy for', 1, function() QUnit.test('should use a default `start` of `0` and a default `end` of `arra
{ y.length`', function(assert) {
var actual = _.filter([1, 2, 3], function(num) { assert.expect(1);
return num % 2;
});
deepEqual(actual, [1, 3]); var array = [1, 2, 3];
assert.deepEqual(_.fill(array, 'a'), ['a', 'a', 'a']);
}); });
test('should iterate correctly over an object with numeric keys (test in Mob QUnit.test('should use `undefined` for `value` if not provided', function(as
ile Safari 8)', 1, function() { sert) {
// Trigger a Mobile Safari 8 JIT bug. assert.expect(2);
// See https://github.com/lodash/lodash/issues/799.
var counter = 0,
object = { '1': 'foo', '8': 'bar', '50': 'baz' };
_.times(1000, function() { var array = [1, 2, 3],
_.filter([], _.constant(true)); actual = _.fill(array);
});
_.filter(object, function() {
counter++;
return true;
});
strictEqual(counter, 3);
});
test('should be aliased', 1, function() { assert.deepEqual(actual, Array(3));
strictEqual(_.select, _.filter); assert.ok(lodashStable.every(actual, function(value, index) {
return index in actual;
}));
}); });
}());
/*--------------------------------------------------------------------------*/
_.each(['find', 'findLast', 'findIndex', 'findLastIndex', 'findKey', 'findLast QUnit.test('should work with a positive `start`', function(assert) {
Key'], function(methodName) { assert.expect(1);
QUnit.module('lodash.' + methodName);
var func = _[methodName];
(function() { var array = [1, 2, 3];
var objects = [ assert.deepEqual(_.fill(array, 'a', 1), [1, 'a', 'a']);
{ 'a': 0, 'b': 0 }, });
{ 'a': 1, 'b': 1 },
{ 'a': 2, 'b': 2 }
];
var expected = ({ QUnit.test('should work with a `start` >= `array.length`', function(assert)
'find': [objects[1], undefined, objects[2], objects[1]], {
'findLast': [objects[2], undefined, objects[2], objects[2]], assert.expect(4);
'findIndex': [1, -1, 2, 1],
'findLastIndex': [2, -1, 2, 2],
'findKey': ['1', undefined, '2', '1'],
'findLastKey': ['2', undefined, '2', '2']
})[methodName];
test('should return the correct value', 1, function() { lodashStable.each([3, 4, Math.pow(2, 32), Infinity], function(start) {
strictEqual(func(objects, function(object) { return object.a; }), expect var array = [1, 2, 3];
ed[0]); assert.deepEqual(_.fill(array, 'a', start), [1, 2, 3]);
}); });
});
test('should work with a `thisArg`', 1, function() { QUnit.test('should treat falsey `start` values as `0`', function(assert) {
strictEqual(func(objects, function(object, index) { return this[index].a assert.expect(1);
; }, objects), expected[0]);
});
test('should return `' + expected[1] + '` if value is not found', 1, funct var expected = lodashStable.map(falsey, lodashStable.constant(['a', 'a', '
ion() { a']));
strictEqual(func(objects, function(object) { return object.a === 3; }),
expected[1]);
});
test('should work with a "_.pluck" style `predicate`', 1, function() { var actual = lodashStable.map(falsey, function(start) {
strictEqual(func(objects, 'b'), expected[3]); var array = [1, 2, 3];
return _.fill(array, 'a', start);
}); });
test('should work with a "_.where" style `predicate`', 1, function() { assert.deepEqual(actual, expected);
strictEqual(func(objects, { 'b': 2 }), expected[2]); });
});
test('should return `' + expected[1] + '` for empty collections', 1, funct QUnit.test('should work with a negative `start`', function(assert) {
ion() { assert.expect(1);
var actual = [],
emptyValues = _.endsWith(methodName, 'Index') ? _.reject(empties, _.
isPlainObject) : empties,
expecting = _.map(emptyValues, function() { return expected[1]; });
_.each(emptyValues, function(value) { var array = [1, 2, 3];
try { assert.deepEqual(_.fill(array, 'a', -1), [1, 2, 'a']);
actual.push(func(value, { 'a': 3 })); });
} catch(e) {}
});
deepEqual(actual, expecting); QUnit.test('should work with a negative `start` <= negative `array.length`',
function(assert) {
assert.expect(3);
lodashStable.each([-3, -4, -Infinity], function(start) {
var array = [1, 2, 3];
assert.deepEqual(_.fill(array, 'a', start), ['a', 'a', 'a']);
}); });
}()); });
(function() { QUnit.test('should work with `start` >= `end`', function(assert) {
var expected = ({ assert.expect(2);
'find': 1,
'findLast': 2,
'findKey': 'a',
'findLastKey': 'b'
})[methodName];
if (expected != null) { lodashStable.each([2, 3], function(start) {
test('should work with an object for `collection`', 1, function() { var array = [1, 2, 3];
var actual = func({ 'a': 1, 'b': 2, 'c': 3 }, function(num) { assert.deepEqual(_.fill(array, 'a', start, 2), [1, 2, 3]);
return num < 3; });
}); });
strictEqual(actual, expected); QUnit.test('should work with a positive `end`', function(assert) {
}); assert.expect(1);
}
}());
(function() { var array = [1, 2, 3];
var expected = ({ assert.deepEqual(_.fill(array, 'a', 0, 1), ['a', 2, 3]);
'find': 'a', });
'findLast': 'b',
'findIndex': 0,
'findLastIndex': 1
})[methodName];
if (expected != null) { QUnit.test('should work with a `end` >= `array.length`', function(assert) {
test('should work with a string for `collection`', 1, function() { assert.expect(4);
var actual = func('abc', function(chr, index) {
return index < 2;
});
strictEqual(actual, expected); lodashStable.each([3, 4, Math.pow(2, 32), Infinity], function(end) {
}); var array = [1, 2, 3];
} assert.deepEqual(_.fill(array, 'a', 0, end), ['a', 'a', 'a']);
if (methodName == 'find') { });
test('should be aliased', 1, function() { });
strictEqual(_.detect, func);
});
}
}());
});
/*--------------------------------------------------------------------------*/ QUnit.test('should treat falsey `end` values, except `undefined`, as `0`', f
unction(assert) {
assert.expect(1);
QUnit.module('lodash.findWhere'); var expected = lodashStable.map(falsey, function(value) {
return value === undefined ? ['a', 'a', 'a'] : [1, 2, 3];
});
(function() { var actual = lodashStable.map(falsey, function(end) {
var objects = [ var array = [1, 2, 3];
{ 'a': 1 }, return _.fill(array, 'a', 0, end);
{ 'a': 1 }, });
{ 'a': 1, 'b': 2 },
{ 'a': 2, 'b': 2 },
{ 'a': 3 }
];
test('should filter by `source` properties', 6, function() { assert.deepEqual(actual, expected);
strictEqual(_.findWhere(objects, { 'a': 1 }), objects[0]);
strictEqual(_.findWhere(objects, { 'a': 2 }), objects[3]);
strictEqual(_.findWhere(objects, { 'a': 3 }), objects[4]);
strictEqual(_.findWhere(objects, { 'b': 1 }), undefined);
strictEqual(_.findWhere(objects, { 'b': 2 }), objects[2]);
strictEqual(_.findWhere(objects, { 'a': 1, 'b': 2 }), objects[2]);
}); });
test('should work with a function for `source`', 1, function() { QUnit.test('should work with a negative `end`', function(assert) {
function source() {} assert.expect(1);
source.a = 2;
strictEqual(_.findWhere(objects, source), objects[3]); var array = [1, 2, 3];
assert.deepEqual(_.fill(array, 'a', 0, -1), ['a', 'a', 3]);
}); });
test('should match all elements when provided an empty `source`', 1, functio QUnit.test('should work with a negative `end` <= negative `array.length`', f
n() { unction(assert) {
var expected = _.map(empties, _.constant(true)); assert.expect(3);
var actual = _.map(empties, function(value) { lodashStable.each([-3, -4, -Infinity], function(end) {
return _.findWhere(objects, value) === objects[0]; var array = [1, 2, 3];
assert.deepEqual(_.fill(array, 'a', 0, end), [1, 2, 3]);
}); });
deepEqual(actual, expected);
}); });
}());
/*--------------------------------------------------------------------------*/ QUnit.test('should coerce `start` and `end` to integers', function(assert) {
assert.expect(1);
QUnit.module('lodash.first'); var positions = [[0.1, 1.6], ['0', 1], [0, '1'], ['1'], [NaN, 1], [1, NaN] ];
(function() { var actual = lodashStable.map(positions, function(pos) {
var array = [1, 2, 3]; var array = [1, 2, 3];
return _.fill.apply(_, [array, 'a'].concat(pos));
});
test('should return the first element', 1, function() { assert.deepEqual(actual, [['a', 2, 3], ['a', 2, 3], ['a', 2, 3], [1, 'a',
strictEqual(_.first(array), 1); 'a'], ['a', 2, 3], [1, 2, 3]]);
}); });
test('should return `undefined` when querying empty arrays', 1, function() { QUnit.test('should work as an iteratee for methods like `_.map`', function(a
var array = []; ssert) {
array['-1'] = 1; assert.expect(1);
strictEqual(_.first(array), undefined);
});
test('should work as an iteratee for `_.map`', 1, function() { var array = [[1, 2], [3, 4]],
var array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]], actual = lodashStable.map(array, _.fill);
actual = _.map(array, _.first);
deepEqual(actual, [1, 4, 7]); assert.deepEqual(actual, [[0, 0], [1, 1]]);
}); });
test('should return an unwrapped value when chaining', 1, function() { QUnit.test('should return a wrapped value when chaining', function(assert) {
if (!isNpm) { assert.expect(3);
strictEqual(_(array).first(), 1);
}
else {
skipTest();
}
});
test('should work in a lazy chain sequence', 1, function() {
if (!isNpm) { if (!isNpm) {
var array = [1, 2, 3, 4]; var array = [1, 2, 3],
wrapped = _(array).fill('a'),
var wrapped = _(array).filter(function(value) { actual = wrapped.value();
return value % 2 == 0;
});
strictEqual(wrapped.first(), 2); assert.ok(wrapped instanceof _);
assert.deepEqual(actual, ['a', 'a', 'a']);
assert.strictEqual(actual, array);
} }
else { else {
skipTest(); skipTest(assert, 3);
} }
}); });
test('should be aliased', 1, function() {
strictEqual(_.head, _.first);
});
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.take'); QUnit.module('lodash.filter');
(function() { (function() {
var array = [1, 2, 3]; var array = [1, 2, 3];
test('should take the first two elements', 1, function() { QUnit.test('should return elements `predicate` returns truthy for', function
deepEqual(_.take(array, 2), [1, 2]); (assert) {
}); assert.expect(1);
test('should treat falsey `n` values, except nullish, as `0`', 1, function() assert.deepEqual(_.filter(array, isEven), [2]);
{ });
var expected = _.map(falsey, function(value) {
return value == null ? [1] : [];
});
var actual = _.map(falsey, function(n) { QUnit.test('should iterate over an object with numeric keys (test in Mobile
return _.take(array, n); Safari 8)', function(assert) {
}); assert.expect(1);
deepEqual(actual, expected); // Trigger a Mobile Safari 8 JIT bug.
}); // See https://github.com/lodash/lodash/issues/799.
var counter = 0,
object = { '1': 'foo', '8': 'bar', '50': 'baz' };
test('should return an empty array when `n` < `1`', 3, function() { lodashStable.times(1000, function(assert) {
_.each([0, -1, -Infinity], function(n) { _.filter([], alwaysTrue);
deepEqual(_.take(array, n), []);
}); });
});
test('should return all elements when `n` >= `array.length`', 4, function() _.filter(object, function() {
{ counter++;
_.each([3, 4, Math.pow(2, 32), Infinity], function(n) { return true;
deepEqual(_.take(array, n), array);
}); });
});
test('should work as an iteratee for `_.map`', 1, function() { assert.strictEqual(counter, 3);
var array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]],
actual = _.map(array, _.take);
deepEqual(actual, [[1], [4], [7]]);
}); });
}());
test('should return a wrapped value when chaining', 2, function() { /*--------------------------------------------------------------------------*/
if (!isNpm) {
var wrapped = _(array).take(2);
ok(wrapped instanceof _);
deepEqual(wrapped.value(), [1, 2]);
}
else {
skipTest(2);
}
});
test('should work in a lazy chain sequence', 4, function() { lodashStable.each(['find', 'findLast', 'findIndex', 'findLastIndex', 'findKey'
if (!isNpm) { , 'findLastKey'], function(methodName) {
var array = [1, 2, 3, 4, 5, 6, 7, 8], QUnit.module('lodash.' + methodName);
predicate = function(value) { return value > 1; },
actual = _(array).take(2).take().value();
deepEqual(actual, [1]); var func = _[methodName],
isFindKey = /Key$/.test(methodName);
actual = _(array).filter(predicate).take(2).take().value(); (function() {
deepEqual(actual, [2]); var objects = [
{ 'a': 0, 'b': 0 },
{ 'a': 1, 'b': 1 },
{ 'a': 2, 'b': 2 }
];
actual = _(array).take(6).takeRight(4).take(2).takeRight().value(); var expected = ({
deepEqual(actual, [4]); 'find': [objects[1], undefined, objects[2], objects[1]],
'findLast': [objects[2], undefined, objects[2], objects[2]],
'findIndex': [1, -1, 2, 1],
'findLastIndex': [2, -1, 2, 2],
'findKey': ['1', undefined, '2', '1'],
'findLastKey': ['2', undefined, '2', '2']
})[methodName];
actual = _(array).filter(predicate).take(6).takeRight(4).take(2).takeRig QUnit.test('should return the found value', function(assert) {
ht().value(); assert.expect(1);
deepEqual(actual, [5]);
}
else {
skipTest(4);
}
});
}());
/*--------------------------------------------------------------------------*/ assert.strictEqual(func(objects, function(object) { return object.a; }),
expected[0]);
});
QUnit.module('lodash.takeRight'); QUnit.test('should return `' + expected[1] + '` if value is not found', fu
nction(assert) {
assert.expect(1);
(function() { assert.strictEqual(func(objects, function(object) { return object.a ===
var array = [1, 2, 3]; 3; }), expected[1]);
});
test('should take the last two elements', 1, function() { QUnit.test('should work with a "_.matches" style `predicate`', function(as
deepEqual(_.takeRight(array, 2), [2, 3]); sert) {
}); assert.expect(1);
test('should treat falsey `n` values, except nullish, as `0`', 1, function() assert.strictEqual(func(objects, { 'b': 2 }), expected[2]);
{
var expected = _.map(falsey, function(value) {
return value == null ? [3] : [];
}); });
var actual = _.map(falsey, function(n) { QUnit.test('should work with a "_.matchesProperty" style `predicate`', fun
return _.takeRight(array, n); ction(assert) {
assert.expect(1);
assert.strictEqual(func(objects, ['b', 2]), expected[2]);
}); });
deepEqual(actual, expected); QUnit.test('should work with a "_.property" style `predicate`', function(a
}); ssert) {
assert.expect(1);
test('should return an empty array when `n` < `1`', 3, function() { assert.strictEqual(func(objects, 'b'), expected[3]);
_.each([0, -1, -Infinity], function(n) {
deepEqual(_.takeRight(array, n), []);
}); });
});
test('should return all elements when `n` >= `array.length`', 4, function() QUnit.test('should return `' + expected[1] + '` for empty collections', fu
{ nction(assert) {
_.each([3, 4, Math.pow(2, 32), Infinity], function(n) { assert.expect(1);
deepEqual(_.takeRight(array, n), array);
});
});
test('should work as an iteratee for `_.map`', 1, function() { var emptyValues = lodashStable.endsWith(methodName, 'Index') ? lodashSta
var array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]], ble.reject(empties, lodashStable.isPlainObject) : empties,
actual = _.map(array, _.takeRight); expecting = lodashStable.map(emptyValues, lodashStable.constant(expe
cted[1]));
deepEqual(actual, [[3], [6], [9]]); var actual = lodashStable.map(emptyValues, function(value) {
}); try {
return func(value, { 'a': 3 });
} catch (e) {}
});
test('should return a wrapped value when chaining', 2, function() { assert.deepEqual(actual, expecting);
if (!isNpm) { });
var wrapped = _(array).takeRight(2); }());
ok(wrapped instanceof _);
deepEqual(wrapped.value(), [2, 3]);
}
else {
skipTest(2);
}
});
test('should work in a lazy chain sequence', 4, function() { (function() {
if (!isNpm) { var array = [1, 2, 3, 4];
var array = [1, 2, 3, 4, 5, 6, 7, 8],
predicate = function(value) { return value < 8; },
actual = _(array).takeRight(2).takeRight().value();
deepEqual(actual, [8]); var expected = ({
'find': 1,
'findLast': 4,
'findIndex': 0,
'findLastIndex': 3,
'findKey': '0',
'findLastKey': '3'
})[methodName];
actual = _(array).filter(predicate).takeRight(2).takeRight().value(); QUnit.test('should return an unwrapped value when implicitly chaining', fu
deepEqual(actual, [7]); nction(assert) {
assert.expect(1);
actual = _(array).takeRight(6).take(4).takeRight(2).take().value(); if (!isNpm) {
deepEqual(actual, [5]); assert.strictEqual(_(array)[methodName](), expected);
}
else {
skipTest(assert);
}
});
actual = _(array).filter(predicate).takeRight(6).take(4).takeRight(2).ta QUnit.test('should return a wrapped value when explicitly chaining', funct
ke().value(); ion(assert) {
deepEqual(actual, [4]); assert.expect(1);
}
else {
skipTest(4);
}
});
}());
/*--------------------------------------------------------------------------*/ if (!isNpm) {
assert.ok(_(array).chain()[methodName]() instanceof _);
}
else {
skipTest(assert);
}
});
QUnit.module('lodash.takeRightWhile'); QUnit.test('should not execute immediately when explicitly chaining', func
tion(assert) {
assert.expect(1);
(function() { if (!isNpm) {
var array = [1, 2, 3]; var wrapped = _(array).chain()[methodName]();
assert.strictEqual(wrapped.__wrapped__, array);
}
else {
skipTest(assert);
}
});
var objects = [ QUnit.test('should work in a lazy sequence', function(assert) {
{ 'a': 0, 'b': 0 }, assert.expect(2);
{ 'a': 1, 'b': 1 },
{ 'a': 2, 'b': 2 }
];
test('should take elements while `predicate` returns truthy', 1, function() if (!isNpm) {
{ var largeArray = lodashStable.range(1, LARGE_ARRAY_SIZE + 1),
var actual = _.takeRightWhile(array, function(num) { smallArray = array;
return num > 1;
lodashStable.times(2, function(index) {
var array = index ? largeArray : smallArray,
wrapped = _(array).filter(isEven);
assert.strictEqual(wrapped[methodName](), func(lodashStable.filter(a
rray, isEven)));
});
}
else {
skipTest(assert, 2);
}
}); });
}());
deepEqual(actual, [2, 3]); (function() {
}); var expected = ({
'find': 1,
'findLast': 2,
'findKey': 'a',
'findLastKey': 'b'
})[methodName];
test('should provide the correct `predicate` arguments', 1, function() { if (expected != null) {
var args; QUnit.test('should work with an object for `collection`', function(asser
t) {
assert.expect(1);
_.takeRightWhile(array, function() { var actual = func({ 'a': 1, 'b': 2, 'c': 3 }, function(num) {
args = slice.call(arguments); return num < 3;
}); });
deepEqual(args, [3, 2, array]); assert.strictEqual(actual, expected);
}); });
}
}());
});
test('should support the `thisArg` argument', 1, function() { /*--------------------------------------------------------------------------*/
var actual = _.takeRightWhile(array, function(num, index) {
return this[index] > 1;
}, array);
deepEqual(actual, [2, 3]); QUnit.module('lodash.find and lodash.findLast');
});
test('should work with a "_.pluck" style `predicate`', 1, function() { lodashStable.each(['find', 'findLast'], function(methodName) {
deepEqual(_.takeRightWhile(objects, 'b'), objects.slice(1)); var isFind = methodName == 'find';
});
test('should work with a "_.where" style `predicate`', 1, function() { QUnit.test('`_.' + methodName + '` should support shortcut fusion', function
deepEqual(_.takeRightWhile(objects, { 'b': 2 }), objects.slice(2)); (assert) {
}); assert.expect(3);
test('should return a wrapped value when chaining', 2, function() {
if (!isNpm) { if (!isNpm) {
var wrapped = _(array).takeRightWhile(function(num) { var findCount = 0,
return num > 1; mapCount = 0,
}); array = lodashStable.range(1, LARGE_ARRAY_SIZE + 1),
iteratee = function(value) { mapCount++; return square(value); },
predicate = function(value) { findCount++; return isEven(value); },
actual = _(array).map(iteratee)[methodName](predicate);
ok(wrapped instanceof _); assert.strictEqual(findCount, isFind ? 2 : 1);
deepEqual(wrapped.value(), [2, 3]); assert.strictEqual(mapCount, isFind ? 2 : 1);
assert.strictEqual(actual, isFind ? 4 : square(LARGE_ARRAY_SIZE));
} }
else { else {
skipTest(2); skipTest(assert, 3);
} }
}); });
}()); });
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.takeWhile'); QUnit.module('lodash.flip');
(function() { (function() {
var array = [1, 2, 3]; function fn() {
return slice.call(arguments);
var objects = [ }
{ 'a': 2, 'b': 2 },
{ 'a': 1, 'b': 1 },
{ 'a': 0, 'b': 0 }
];
test('should take elements while `predicate` returns truthy', 1, function() QUnit.test('should flip arguments provided to `func`', function(assert) {
{ assert.expect(1);
var actual = _.takeWhile(array, function(num) {
return num < 3;
});
deepEqual(actual, [1, 2]); var flipped = _.flip(fn);
assert.deepEqual(flipped('a', 'b', 'c', 'd'), ['d', 'c', 'b', 'a']);
}); });
}());
test('should provide the correct `predicate` arguments', 1, function() { /*--------------------------------------------------------------------------*/
var args;
_.takeWhile(array, function() { QUnit.module('lodash.flatMap');
args = slice.call(arguments);
});
deepEqual(args, [1, 0, array]); (function() {
}); var array = [1, 2, 3, 4];
test('should support the `thisArg` argument', 1, function() { function duplicate(n) {
var actual = _.takeWhile(array, function(num, index) { return [n, n];
return this[index] < 3; }
}, array);
deepEqual(actual, [1, 2]); QUnit.test('should map values in `array` to a new flattened array', function
}); (assert) {
assert.expect(1);
test('should work with a "_.pluck" style `predicate`', 1, function() { var actual = _.flatMap(array, duplicate),
deepEqual(_.takeWhile(objects, 'b'), objects.slice(0, 2)); expected = lodashStable.flatten(lodashStable.map(array, duplicate));
});
test('should work with a "_.where" style `predicate`', 1, function() { assert.deepEqual(actual, expected);
deepEqual(_.takeWhile(objects, { 'b': 2 }), objects.slice(0, 1));
}); });
test('should return a wrapped value when chaining', 2, function() { QUnit.test('should work in a lazy sequence', function(assert) {
assert.expect(2);
if (!isNpm) { if (!isNpm) {
var wrapped = _(array).takeWhile(function(num) { var largeArray = lodashStable.range(LARGE_ARRAY_SIZE),
return num < 3; smallArray = array;
});
lodashStable.times(2, function(index) {
var array = index ? largeArray : smallArray,
actual = _(array).filter(isEven).flatMap(duplicate).take(2).value(
);
ok(wrapped instanceof _); assert.deepEqual(actual, _.take(_.flatMap(_.filter(array, isEven), dup
deepEqual(wrapped.value(), [1, 2]); licate), 2));
});
} }
else { else {
skipTest(2); skipTest(assert, 2);
} }
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('flatten methods'); QUnit.module('flatten methods');
(function() { (function() {
var args = arguments; var args = arguments;
test('should perform a shallow flatten', 1, function() { QUnit.test('should perform a shallow flatten', function(assert) {
var array = [[['a']], [['b']]]; assert.expect(1);
deepEqual(_.flatten(array), [['a'], ['b']]);
});
test('should work with `isDeep`', 2, function() {
var array = [[['a']], [['b']]],
expected = ['a', 'b'];
deepEqual(_.flatten(array, true), expected); var array = [[['a']], [['b']]];
deepEqual(_.flattenDeep(array), expected); assert.deepEqual(_.flatten(array), [['a'], ['b']]);
}); });
test('should flatten `arguments` objects', 3, function() { QUnit.test('should flatten `arguments` objects', function(assert) {
var array = [args, [args]], assert.expect(2);
expected = [1, 2, 3, args];
deepEqual(_.flatten(array), expected); var array = [args, [args]];
expected = [1, 2, 3, 1, 2, 3]; assert.deepEqual(_.flatten(array), [1, 2, 3, args]);
deepEqual(_.flatten(array, true), expected); assert.deepEqual(_.flattenDeep(array), [1, 2, 3, 1, 2, 3]);
deepEqual(_.flattenDeep(array), expected);
}); });
test('should work as an iteratee for `_.map`', 2, function() { QUnit.test('should treat sparse arrays as dense', function(assert) {
var array = [[[['a']]], [[['b']]]]; assert.expect(6);
deepEqual(_.map(array, _.flatten), [[['a']], [['b']]]);
deepEqual(_.map(array, _.flattenDeep), [['a'], ['b']]);
});
test('should treat sparse arrays as dense', 6, function() {
var array = [[1, 2, 3], Array(3)], var array = [[1, 2, 3], Array(3)],
expected = [1, 2, 3]; expected = [1, 2, 3];
expected.push(undefined, undefined, undefined); expected.push(undefined, undefined, undefined);
_.each([_.flatten(array), _.flatten(array, true), _.flattenDeep(array)], f lodashStable.each([_.flatten(array), _.flatten(array, true), _.flattenDeep
unction(actual) { (array)], function(actual) {
deepEqual(actual, expected); assert.deepEqual(actual, expected);
ok('4' in actual); assert.ok('4' in actual);
}); });
}); });
test('should work with extremely large arrays', 3, function() { QUnit.test('should work with extremely large arrays', function(assert) {
assert.expect(3);
// Test in modern browsers only to avoid browser hangs. // Test in modern browsers only to avoid browser hangs.
_.times(3, function(index) { lodashStable.times(3, function(index) {
if (freeze) { if (freeze) {
var expected = Array(5e5); var expected = Array(5e5);
try { try {
if (index) { if (index) {
var actual = actual == 1 ? _.flatten([expected], true) : _.flatten Deep([expected]); var actual = actual == 1 ? _.flatten([expected], true) : _.flatten Deep([expected]);
} else { } else {
actual = _.flatten(expected); actual = _.flatten(expected);
} }
deepEqual(actual, expected); assert.deepEqual(actual, expected);
} catch(e) { } catch (e) {
ok(false, e.message); assert.ok(false, e.message);
} }
} }
else { else {
skipTest(); skipTest(assert);
} }
}); });
}); });
test('should work with empty arrays', 3, function() { QUnit.test('should work with empty arrays', function(assert) {
var array = [[], [[]], [[], [[[]]]]], assert.expect(2);
expected = [[], [], [[[]]]];
deepEqual(_.flatten(array), expected); var array = [[], [[]], [[], [[[]]]]];
expected = []; assert.deepEqual(_.flatten(array), [[], [], [[[]]]]);
deepEqual(_.flatten(array, true), expected); assert.deepEqual(_.flattenDeep(array), []);
deepEqual(_.flattenDeep(array), expected);
}); });
test('should support flattening of nested arrays', 3, function() { QUnit.test('should support flattening of nested arrays', function(assert) {
var array = [1, [2], [3, [4]]], assert.expect(2);
expected = [1, 2, 3, [4]];
deepEqual(_.flatten(array), expected); var array = [1, [2, 3], 4, [[5]]];
expected = [1, 2, 3, 4]; assert.deepEqual(_.flatten(array), [1, 2, 3, 4, [5]]);
deepEqual(_.flatten(array, true), expected); assert.deepEqual(_.flattenDeep(array), [1, 2, 3, 4, 5]);
deepEqual(_.flattenDeep(array), expected);
}); });
test('should return an empty array for non array-like objects', 3, function( QUnit.test('should return an empty array for non array-like objects', functi
) { on(assert) {
assert.expect(3);
var expected = []; var expected = [];
deepEqual(_.flatten({ 'a': 1 }), expected); assert.deepEqual(_.flatten({ 'a': 1 }), expected);
deepEqual(_.flatten({ 'a': 1 }, true), expected); assert.deepEqual(_.flatten({ 'a': 1 }, true), expected);
deepEqual(_.flattenDeep({ 'a': 1 }), expected); assert.deepEqual(_.flattenDeep({ 'a': 1 }), expected);
}); });
test('should return a wrapped value when chaining', 6, function() { QUnit.test('should return a wrapped value when chaining', function(assert) {
assert.expect(4);
if (!isNpm) { if (!isNpm) {
var wrapped = _([1, [2], [3, [4]]]), var wrapped = _([1, [2], [3, [4]]]),
actual = wrapped.flatten(), actual = wrapped.flatten();
expected = [1, 2, 3, [4]];
ok(actual instanceof _);
deepEqual(actual.value(), expected);
expected = [1, 2, 3, 4];
actual = wrapped.flatten(true);
ok(actual instanceof _); assert.ok(actual instanceof _);
deepEqual(actual.value(), expected); assert.deepEqual(actual.value(), [1, 2, 3, [4]]);
actual = wrapped.flattenDeep(); actual = wrapped.flattenDeep();
ok(actual instanceof _); assert.ok(actual instanceof _);
deepEqual(actual.value(), expected); assert.deepEqual(actual.value(), [1, 2, 3, 4]);
} }
else { else {
skipTest(6); skipTest(assert, 4);
} }
}); });
}(1, 2, 3)); }(1, 2, 3));
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('flow methods');
lodashStable.each(['flow', 'flowRight'], function(methodName) {
var func = _[methodName],
isFlow = methodName == 'flow';
QUnit.test('`_.' + methodName + '` should supply each function with the retu
rn value of the previous', function(assert) {
assert.expect(1);
var fixed = function(n) { return n.toFixed(1); },
combined = isFlow ? func(add, square, fixed) : func(fixed, square, add
);
assert.strictEqual(combined(1, 2), '9.0');
});
QUnit.test('`_.' + methodName + '` should return a new function', function(a
ssert) {
assert.expect(1);
assert.notStrictEqual(func(noop), noop);
});
QUnit.test('`_.' + methodName + '` should return an identity function when n
o arguments are provided', function(assert) {
assert.expect(3);
var combined = func();
try {
assert.strictEqual(combined('a'), 'a');
} catch (e) {
assert.ok(false, e.message);
}
assert.strictEqual(combined.length, 0);
assert.notStrictEqual(combined, identity);
});
QUnit.test('`_.' + methodName + '` should work with a curried function and `
_.head`', function(assert) {
assert.expect(1);
var curried = _.curry(identity);
var combined = isFlow
? func(_.head, curried)
: func(curried, _.head);
assert.strictEqual(combined([1]), 1);
});
QUnit.test('`_.' + methodName + '` should support shortcut fusion', function
(assert) {
assert.expect(6);
var filterCount,
mapCount,
array = lodashStable.range(LARGE_ARRAY_SIZE),
iteratee = function(value) { mapCount++; return square(value); },
predicate = function(value) { filterCount++; return isEven(value); };
lodashStable.times(2, function(index) {
var filter1 = _.filter,
filter2 = _.curry(_.rearg(_.ary(_.filter, 2), 1, 0), 2),
filter3 = (_.filter = index ? filter2 : filter1, filter2(predicate))
;
var map1 = _.map,
map2 = _.curry(_.rearg(_.ary(_.map, 2), 1, 0), 2),
map3 = (_.map = index ? map2 : map1, map2(iteratee));
var take1 = _.take,
take2 = _.curry(_.rearg(_.ary(_.take, 2), 1, 0), 2),
take3 = (_.take = index ? take2 : take1, take2(2));
var combined = isFlow
? func(map3, filter3, _.compact, take3)
: func(take3, _.compact, filter3, map3);
filterCount = mapCount = 0;
assert.deepEqual(combined(array), [4, 16]);
if (!isNpm && WeakMap && WeakMap.name) {
assert.strictEqual(filterCount, 5, 'filterCount');
assert.strictEqual(mapCount, 5, 'mapCount');
}
else {
skipTest(assert, 2);
}
_.filter = filter1;
_.map = map1;
_.take = take1;
});
});
QUnit.test('`_.' + methodName + '` should work with curried functions with p
laceholders', function(assert) {
assert.expect(1);
var curried = _.curry(_.ary(_.map, 2), 2),
getProp = curried(curried.placeholder, 'a'),
objects = [{ 'a': 1 }, { 'a': 2 }, { 'a': 1 }];
var combined = isFlow
? func(getProp, _.uniq)
: func(_.uniq, getProp);
assert.deepEqual(combined(objects), [1, 2]);
});
QUnit.test('`_.' + methodName + '` should return a wrapped value when chaini
ng', function(assert) {
assert.expect(1);
if (!isNpm) {
var wrapped = _(noop)[methodName]();
assert.ok(wrapped instanceof _);
}
else {
skipTest(assert);
}
});
});
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.forEach'); QUnit.module('lodash.forEach');
(function() { (function() {
test('should be aliased', 1, function() { QUnit.test('should be aliased', function(assert) {
strictEqual(_.each, _.forEach); assert.expect(1);
assert.strictEqual(_.each, _.forEach);
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.forEachRight'); QUnit.module('lodash.forEachRight');
(function() { (function() {
test('should be aliased', 1, function() { QUnit.test('should be aliased', function(assert) {
strictEqual(_.eachRight, _.forEachRight); assert.expect(1);
assert.strictEqual(_.eachRight, _.forEachRight);
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('forIn methods'); QUnit.module('forIn methods');
_.each(['forIn', 'forInRight'], function(methodName) { lodashStable.each(['forIn', 'forInRight'], function(methodName) {
var func = _[methodName]; var func = _[methodName];
test('`_.' + methodName + '` iterates over inherited properties', 1, functio QUnit.test('`_.' + methodName + '` iterates over inherited properties', func
n() { tion(assert) {
assert.expect(1);
function Foo() { this.a = 1; } function Foo() { this.a = 1; }
Foo.prototype.b = 2; Foo.prototype.b = 2;
var keys = []; var keys = [];
func(new Foo, function(value, key) { keys.push(key); }); func(new Foo, function(value, key) { keys.push(key); });
deepEqual(keys.sort(), ['a', 'b']); assert.deepEqual(keys.sort(), ['a', 'b']);
}); });
}); });
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('forOwn methods'); QUnit.module('forOwn methods');
_.each(['forOwn', 'forOwnRight'], function(methodName) { lodashStable.each(['forOwn', 'forOwnRight'], function(methodName) {
var func = _[methodName]; var func = _[methodName];
test('iterates over the `length` property', 1, function() { QUnit.test('should iterate over `length` properties', function(assert) {
assert.expect(1);
var object = { '0': 'zero', '1': 'one', 'length': 2 }, var object = { '0': 'zero', '1': 'one', 'length': 2 },
props = []; props = [];
func(object, function(value, prop) { props.push(prop); }); func(object, function(value, prop) { props.push(prop); });
deepEqual(props.sort(), ['0', '1', 'length']); assert.deepEqual(props.sort(), ['0', '1', 'length']);
}); });
}); });
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('iteration methods'); QUnit.module('iteration methods');
(function() { (function() {
var methods = [ var methods = [
'_baseEach',
'countBy', 'countBy',
'every', 'every',
'filter', 'filter',
'find', 'find',
'findIndex', 'findIndex',
'findKey', 'findKey',
'findLast', 'findLast',
'findLastIndex', 'findLastIndex',
'findLastKey', 'findLastKey',
'forEach',
'forEachRight', 'forEachRight',
'forIn', 'forIn',
'forInRight', 'forInRight',
'forOwn', 'forOwn',
'forOwnRight', 'forOwnRight',
'groupBy', 'groupBy',
'indexBy', 'keyBy',
'map', 'map',
'max', 'mapKeys',
'min', 'mapValues',
'maxBy',
'minBy',
'omitBy',
'partition', 'partition',
'pickBy',
'reject', 'reject',
'some' 'some'
]; ];
var arrayMethods = [ var arrayMethods = [
'findIndex', 'findIndex',
'findLastIndex' 'findLastIndex',
'maxBy',
'minBy'
]; ];
var collectionMethods = [ var collectionMethods = [
'_baseEach',
'countBy', 'countBy',
'every', 'every',
'filter', 'filter',
'find', 'find',
'findLast', 'findLast',
'forEach', 'forEach',
'forEachRight', 'forEachRight',
'groupBy', 'groupBy',
'indexBy', 'keyBy',
'map', 'map',
'max',
'min',
'partition', 'partition',
'reduce', 'reduce',
'reduceRight', 'reduceRight',
'reject', 'reject',
'some' 'some'
]; ];
var forInMethods = [ var forInMethods = [
'forIn', 'forIn',
'forInRight' 'forInRight',
'omitBy',
'pickBy'
]; ];
var iterationMethods = [ var iterationMethods = [
'_baseEach',
'forEach', 'forEach',
'forEachRight', 'forEachRight',
'forIn',