"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "test/test.js" between
lodash-4.0.0.tar.gz and lodash-4.17.21.tar.gz

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

test.js  (lodash-4.0.0):test.js  (lodash-4.17.21)
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 the maximum memoize cache size. */
var MAX_MEMOIZE_SIZE = 500;
/** Used as references for various `Number` constants. */ /** Used as references for various `Number` constants. */
var MAX_SAFE_INTEGER = 9007199254740991, var MAX_SAFE_INTEGER = 9007199254740991,
MAX_INTEGER = 1.7976931348623157e+308; MAX_INTEGER = 1.7976931348623157e+308;
/** Used as references for the maximum length and index of an array. */ /** Used as references for the maximum length and index of an array. */
var MAX_ARRAY_LENGTH = 4294967295, var MAX_ARRAY_LENGTH = 4294967295,
MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1; MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1;
/** `Object#toString` result references. */ /** `Object#toString` result references. */
var funcTag = '[object Function]', var funcTag = '[object Function]',
skipping to change at line 36 skipping to change at line 39
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,
funcProto = Function.prototype, funcProto = Function.prototype,
objectProto = Object.prototype, objectProto = Object.prototype,
numberProto = Number.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, process = root.process,
argv = root.process && process.argv, amd = root.define ? define.amd : undefined,
ArrayBuffer = root.ArrayBuffer, args = toArgs([1, 2, 3]),
argv = process ? process.argv : undefined,
defineProperty = Object.defineProperty, defineProperty = Object.defineProperty,
document = !phantom && root.document, document = phantom ? undefined : root.document,
body = root.document && root.document.body, body = root.document ? root.document.body : undefined,
create = Object.create, create = Object.create,
fnToString = funcProto.toString, fnToString = funcProto.toString,
freeze = Object.freeze, freeze = Object.freeze,
getSymbols = Object.getOwnPropertySymbols,
identity = function(value) { return value; }, identity = function(value) { return value; },
JSON = root.JSON,
Map = root.Map,
noop = function() {}, noop = function() {},
objToString = objectProto.toString, objToString = objectProto.toString,
params = argv, params = argv,
push = arrayProto.push, push = arrayProto.push,
realm = {}, realm = {},
Set = root.Set,
slice = arrayProto.slice, slice = arrayProto.slice,
strictArgs = (function() { 'use strict'; return arguments; }(1, 2, 3));
var ArrayBuffer = root.ArrayBuffer,
Buffer = root.Buffer,
Map = root.Map,
Promise = root.Promise,
Proxy = root.Proxy,
Set = root.Set,
Symbol = root.Symbol, Symbol = root.Symbol,
symbol = Symbol ? Symbol('a') : undefined,
Uint8Array = root.Uint8Array, Uint8Array = root.Uint8Array,
WeakMap = root.WeakMap; WeakMap = root.WeakMap,
WeakSet = root.WeakSet;
var arrayBuffer = ArrayBuffer ? new ArrayBuffer(2) : undefined,
map = Map ? new Map : undefined,
promise = Promise ? Promise.resolve(1) : undefined,
set = Set ? new Set : undefined,
symbol = Symbol ? Symbol('a') : undefined,
weakMap = WeakMap ? new WeakMap : undefined,
weakSet = WeakSet ? new WeakSet : undefined;
/** Math helpers. */ /** Math helpers. */
var add = function(x, y) { return x + y; }, var add = function(x, y) { return x + y; },
doubled = function(n) { return n * 2; }, doubled = function(n) { return n * 2; },
isEven = function(n) { return n % 2 == 0; }, isEven = function(n) { return n % 2 == 0; },
square = function(n) { return n * n; }; square = function(n) { return n * n; };
/** Constant functions. */ /** Stub functions. */
var alwaysA = function() { return 'a'; }, var stubA = function() { return 'a'; },
alwaysB = function() { return 'b'; }, stubB = function() { return 'b'; },
alwaysC = function() { return 'c'; }; stubC = function() { return 'c'; };
var alwaysTrue = function() { return true; }, var stubTrue = function() { return true; },
alwaysFalse = function() { return false; }; stubFalse = function() { return false; };
var alwaysNaN = function() { return NaN; }, var stubNaN = function() { return NaN; },
alwaysNull = function() { return null; }, stubNull = function() { return null; };
alwaysUndefined = function() { return undefined; };
var stubZero = function() { return 0; },
var alwaysZero = function() { return 0; }, stubOne = function() { return 1; },
alwaysOne = function() { return 1; }, stubTwo = function() { return 2; },
alwaysTwo = function() { return 2; }, stubThree = function() { return 3; },
alwaysThree = function() { return 3; }, stubFour = function() { return 4; };
alwaysFour = function() { return 4; };
var stubArray = function() { return []; },
var alwaysEmptyArray = function() { return []; }, stubObject = function() { return {}; },
alwaysEmptyObject = function() { return {}; }, stubString = function() { return ''; };
alwaysEmptyString = function() { return ''; };
/** List of Latin Unicode letters. */
var burredLetters = [
// Latin-1 Supplement letters.
'\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', '\xdf',
'\xe0', '\xe1', '\xe2', '\xe3', '\xe4', '\xe5', '\xe6', '\xe7', '\xe8', '\xe
9', '\xea', '\xeb', '\xec', '\xed', '\xee', '\xef',
'\xf0', '\xf1', '\xf2', '\xf3', '\xf4', '\xf5', '\xf6', '\xf8', '\xf
9', '\xfa', '\xfb', '\xfc', '\xfd', '\xfe', '\xff',
// Latin Extended-A letters.
'\u0100', '\u0101', '\u0102', '\u0103', '\u0104', '\u0105', '\u0106', '\u010
7', '\u0108', '\u0109', '\u010a', '\u010b', '\u010c', '\u010d', '\u010e', '\u010
f',
'\u0110', '\u0111', '\u0112', '\u0113', '\u0114', '\u0115', '\u0116', '\u011
7', '\u0118', '\u0119', '\u011a', '\u011b', '\u011c', '\u011d', '\u011e', '\u011
f',
'\u0120', '\u0121', '\u0122', '\u0123', '\u0124', '\u0125', '\u0126', '\u012
7', '\u0128', '\u0129', '\u012a', '\u012b', '\u012c', '\u012d', '\u012e', '\u012
f',
'\u0130', '\u0131', '\u0132', '\u0133', '\u0134', '\u0135', '\u0136', '\u013
7', '\u0138', '\u0139', '\u013a', '\u013b', '\u013c', '\u013d', '\u013e', '\u013
f',
'\u0140', '\u0141', '\u0142', '\u0143', '\u0144', '\u0145', '\u0146', '\u014
7', '\u0148', '\u0149', '\u014a', '\u014b', '\u014c', '\u014d', '\u014e', '\u014
f',
'\u0150', '\u0151', '\u0152', '\u0153', '\u0154', '\u0155', '\u0156', '\u015
7', '\u0158', '\u0159', '\u015a', '\u015b', '\u015c', '\u015d', '\u015e', '\u015
f',
'\u0160', '\u0161', '\u0162', '\u0163', '\u0164', '\u0165', '\u0166', '\u016
7', '\u0168', '\u0169', '\u016a', '\u016b', '\u016c', '\u016d', '\u016e', '\u016
f',
'\u0170', '\u0171', '\u0172', '\u0173', '\u0174', '\u0175', '\u0176', '\u017
7', '\u0178', '\u0179', '\u017a', '\u017b', '\u017c', '\u017d', '\u017e', '\u017
f'
];
/** 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 converted Latin Unicode letters. */
var deburredLetters = [
// Converted Latin-1 Supplement letters.
'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
',
'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',
// Converted Latin Extended-A letters.
'A', 'a', 'A', 'a', 'A', 'a', 'C', 'c', 'C', 'c', 'C', 'c', 'C', 'c',
'D', 'd', 'D', 'd', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e',
'G', 'g', 'G', 'g', 'G', 'g', 'G', 'g', 'H', 'h', 'H', 'h',
'I', 'i', 'I', 'i', 'I', 'i', 'I', 'i', 'I', 'i', 'IJ', 'ij', 'J', 'j',
'K', 'k', 'k', 'L', 'l', 'L', 'l', 'L', 'l', 'L', 'l', 'L', 'l',
'N', 'n', 'N', 'n', 'N', 'n', "'n", 'N', 'n',
'O', 'o', 'O', 'o', 'O', 'o', 'Oe', 'oe',
'R', 'r', 'R', 'r', 'R', 'r', 'S', 's', 'S', 's', 'S', 's', 'S', 's',
'T', 't', 'T', 't', 'T', 't',
'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u',
'W', 'w', 'Y', 'y', 'Y', 'Z', 'z', 'Z', 'z', 'Z', 'z', 's'
];
/** Used to provide falsey values to methods. */
var falsey = [, null, undefined, false, 0, NaN, ''];
/** Used to specify the emoji style glyph variant of characters. */
var emojiVar = '\ufe0f';
/** Used to provide empty values to methods. */
var empties = [[], {}].concat(falsey.slice(1));
/** Used to test error objects. */
var errors = [
new Error,
new EvalError,
new RangeError,
new ReferenceError,
new SyntaxError,
new TypeError,
new URIError
];
/** List of fitzpatrick modifiers. */
var fitzModifiers = [
'\ud83c\udffb',
'\ud83c\udffc',
'\ud83c\udffd',
'\ud83c\udffe',
'\ud83c\udfff'
];
/** Used to provide primitive values to methods. */
var primitives = [null, undefined, false, true, 1, NaN, 'a'];
/** Used to check whether methods support typed arrays. */
var typedArrays = [
'Float32Array',
'Float64Array',
'Int8Array',
'Int16Array',
'Int32Array',
'Uint8Array',
'Uint8ClampedArray',
'Uint16Array',
'Uint32Array'
];
/** Used to check whether methods support array views. */
var arrayViews = typedArrays.concat('DataView');
/** 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 = 2, var min = 2,
result = params || []; result = params || [];
if (phantom) { if (phantom) {
min = 0; min = 0;
result = params = phantom.args || require('system').args; result = params = phantom.args || require('system').args;
} }
skipping to change at line 124 skipping to change at line 239
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 'isModularize': /\b(?:amd|commonjs|es|node|npm|(index|main)\.js)\b/.test(fil
ilePath), ePath),
'isStrict': /\bes6?\b/.test(filePath), 'isStrict': /\bes\b/.test(filePath) || 'default' in require(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];
/** 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. */
skipping to change at line 149 skipping to change at line 264
var isPhantom = phantom || (typeof callPhantom == 'function'); var isPhantom = phantom || (typeof callPhantom == 'function');
/** Detect if lodash is in strict mode. */ /** Detect if lodash is in strict mode. */
var isStrict = ui.isStrict; var isStrict = ui.isStrict;
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
// Leak to avoid sporadic `noglobals` fails on Edge in Sauce Labs. // Leak to avoid sporadic `noglobals` fails on Edge in Sauce Labs.
root.msWDfn = undefined; root.msWDfn = undefined;
// Assign `setTimeout` to itself to avoid being flagged as a leak.
setProperty(root, 'setTimeout', setTimeout);
// 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.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;
skipping to change at line 211 skipping to change at line 329
/** Poison the free variable `root` in Node.js */ /** Poison the free variable `root` in Node.js */
try { try {
defineProperty(global.root, 'root', { defineProperty(global.root, 'root', {
'configurable': false, 'configurable': false,
'enumerable': false, 'enumerable': false,
'get': function() { throw new ReferenceError; } 'get': function() { throw new ReferenceError; }
}); });
} catch (e) {} } catch (e) {}
/** Use a single "load" function. */ /** Load QUnit and extras. */
var load = (!amd && typeof require == 'function') var QUnit = root.QUnit || require('qunit-extras');
? require
: noop; /** Load stable Lodash. */
var lodashStable = root.lodashStable;
/** The unit testing framework. */ if (!lodashStable) {
var QUnit = root.QUnit || (root.QUnit = load('../node_modules/qunitjs/qunit/qu try {
nit.js')); lodashStable = interopRequire('../node_modules/lodash/lodash.js');
} catch (e) {
/** Load stable Lodash and QUnit Extras. */ console.log('Error: The stable lodash dev dependency should be at least a
var lodashStable = root.lodashStable || load('../node_modules/lodash/index.js' version behind master branch.');
); return;
if (lodashStable) { }
lodashStable = lodashStable.runInContext(root); lodashStable = lodashStable.noConflict();
}
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._ = interopRequire(filePath));
_ = load(filePath),
_ = _._ || (isStrict = ui.isStrict = isStrict || 'default' in _, _['default' /** Used to test pseudo private map caches. */
]) || _, var mapCaches = (function() {
(_.runInContext ? _.runInContext(root) : _) var MapCache = (_.memoize || lodashStable.memoize).Cache;
)); var result = {
'Hash': new MapCache().__data__.hash.constructor,
'MapCache': MapCache
};
(_.isMatchWith || lodashStable.isMatchWith)({ 'a': 1 }, { 'a': 1 }, function
() {
var stack = lodashStable.last(arguments);
result.ListCache = stack.__data__.constructor;
result.Stack = stack.constructor;
});
return result;
}());
/** Used to detect instrumented istanbul code coverage runs. */ /** Used to detect instrumented istanbul code coverage runs. */
var coverage = root.__coverage__ || root[lodashStable.findKey(root, function(v alue, key) { var coverage = root.__coverage__ || root[lodashStable.find(lodashStable.keys(r oot), function(key) {
return /^(?:\$\$cov_\d+\$\$)$/.test(key); return /^(?:\$\$cov_\d+\$\$)$/.test(key);
})]; })];
/** Used to restore the `_` reference. */ /** Used to test async functions. */
var oldDash = root._; var asyncFunc = lodashStable.attempt(function() {
return Function('return async () => {}');
});
/** Used to test generator functions. */ /** Used to test generator functions. */
var generator = lodashStable.attempt(function() { var genFunc = lodashStable.attempt(function() {
return Function('return function*(){}'); return Function('return function*(){}');
}); });
/** List of latin-1 supplementary letters to basic latin letters. */ /** Used to restore the `_` reference. */
var burredLetters = [ var oldDash = root._;
'\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',
'\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'
];
/** 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. */
var deburredLetters = [
'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
',
'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'
];
/** 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. */
var falsey = [, '', 0, false, NaN, null, undefined];
/** Used to provide empty values to methods. */
var empties = [[], {}].concat(falsey.slice(1));
/** Used to test error objects. */
var errors = [
new Error,
new EvalError,
new RangeError,
new ReferenceError,
new SyntaxError,
new TypeError,
new URIError
];
/** Used to check whether methods support typed arrays. */
var typedArrays = [
'Float32Array',
'Float64Array',
'Int8Array',
'Int16Array',
'Int32Array',
'Uint8Array',
'Uint8ClampedArray',
'Uint16Array',
'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/bl eeding_edge/test/mjsunit/whitespaces.js). * see [V8's unit test](https://code.google.com/p/v8/source/browse/branches/bl eeding_edge/test/mjsunit/whitespaces.js).
*/ */
var whitespace = lodashStable.filter([ var whitespace = lodashStable.filter([
// Basic whitespace characters. // Basic whitespace characters.
' ', '\t', '\x0b', '\f', '\xa0', '\ufeff', ' ', '\t', '\x0b', '\f', '\xa0', '\ufeff',
// Line terminators. // Line terminators.
'\n', '\r', '\u2028', '\u2029', '\n', '\r', '\u2028', '\u2029',
// Unicode category "Zs" space separators. // Unicode category "Zs" space separators.
'\u1680', '\u180e', '\u2000', '\u2001', '\u2002', '\u2003', '\u2004', '\u200 5', '\u1680', '\u180e', '\u2000', '\u2001', '\u2002', '\u2003', '\u2004', '\u200 5',
'\u2006', '\u2007', '\u2008', '\u2009', '\u200a', '\u202f', '\u205f', '\u300 0' '\u2006', '\u2007', '\u2008', '\u2009', '\u200a', '\u202f', '\u205f', '\u300 0'
], ],
function(chr) { return /\s/.exec(chr); }) function(chr) { return /\s/.exec(chr); })
.join(''); .join('');
/** /**
* Creates a custom error object.
*
* @private
* @constructor
* @param {string} message The error message.
*/
function CustomError(message) {
this.name = 'CustomError';
this.message = message;
}
CustomError.prototype = lodashStable.create(Error.prototype, {
'constructor': CustomError
});
/**
* Removes all own enumerable string keyed properties from a given object.
*
* @private
* @param {Object} object The object to empty.
*/
function emptyObject(object) {
lodashStable.forOwn(object, function(value, key, object) {
delete object[key];
});
}
/**
* 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,
actions = wrapper.__actions__, actions = wrapper.__actions__,
length = actions.length, length = actions.length,
skipping to change at line 361 skipping to change at line 450
var args = [result], var args = [result],
action = actions[index]; action = actions[index];
push.apply(args, action.args); push.apply(args, action.args);
result = action.func.apply(action.thisArg, args); result = action.func.apply(action.thisArg, args);
} }
return result; return result;
} }
/** /**
* Removes all own enumerable properties from a given object. * Loads the module of `id`. If the module has an `exports.default`, the
* exported default value is returned as the resolved module.
* *
* @private * @private
* @param {Object} object The object to empty. * @param {string} id The identifier of the module to resolve.
* @returns {*} Returns the resolved module.
*/ */
function emptyObject(object) { function interopRequire(id) {
lodashStable.forOwn(object, function(value, key, object) { var result = require(id);
delete object[key]; return 'default' in result ? result['default'] : result;
});
} }
/** /**
* 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
skipping to change at line 405 skipping to change at line 495
return object; 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 {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(assert, count) { function skipAssert(assert, count) {
count || (count = 1); count || (count = 1);
while (count--) { while (count--) {
assert.ok(true, 'test skipped'); assert.ok(true, 'test skipped');
} }
} }
/**
* Converts `array` to an `arguments` object.
*
* @private
* @param {Array} array The array to convert.
* @returns {Object} Returns the converted `arguments` object.
*/
function toArgs(array) {
return (function() { return arguments; }.apply(undefined, array));
}
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
// Add bizarro values. // Add bizarro values.
(function() { (function() {
if (document || (typeof require != 'function')) { if (document || (typeof require != 'function')) {
return; return;
} }
var nativeString = fnToString.call(toString), var nativeString = fnToString.call(toString),
reToString = /toString/g; reToString = /toString/g;
function createToString(funcName) { function createToString(funcName) {
return lodashStable.constant(nativeString.replace(reToString, funcName)); return lodashStable.constant(nativeString.replace(reToString, funcName));
} }
// 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 = lodashStable.has(this, 'toString') ? this.toString() : fnToSt ring.call(this);
setProperty(funcProto, 'toString', wrapper); setProperty(funcProto, 'toString', wrapper);
return result; return result;
}); });
// Add prototype extensions. // Add prototype extensions.
funcProto._method = noop; funcProto._method = noop;
// Set bad shims. // Set bad shims.
setProperty(Object, 'create', undefined);
setProperty(Object, 'getOwnPropertySymbols', undefined);
var _propertyIsEnumerable = objectProto.propertyIsEnumerable; var _propertyIsEnumerable = objectProto.propertyIsEnumerable;
setProperty(objectProto, 'propertyIsEnumerable', function(key) { setProperty(objectProto, 'propertyIsEnumerable', function(key) {
return !(key == 'valueOf' && this && this.valueOf === 1) && _propertyIsEnu merable.call(this, key); return !(key == 'valueOf' && this && this.valueOf === 1) && _propertyIsEnu merable.call(this, key);
}); });
if (Buffer) {
defineProperty(root, 'Buffer', {
'configurable': true,
'enumerable': true,
'get': function get() {
var caller = get.caller,
name = caller ? caller.name : '';
if (!(name == 'runInContext' || name.length == 1 || /\b_\.isBuffer\b/.
test(caller))) {
return Buffer;
}
}
});
}
if (Map) { if (Map) {
setProperty(root, 'Map', (function() { setProperty(root, 'Map', (function() {
var count = 0; var count = 0;
return function() { return function() {
if (count++) { if (count++) {
return new Map; return new Map;
} }
var result = {};
setProperty(root, 'Map', Map); setProperty(root, 'Map', Map);
return result; return {};
}; };
}())); }()));
setProperty(root.Map, 'toString', createToString('Map')); setProperty(root.Map, 'toString', createToString('Map'));
} }
setProperty(Object, 'create', noop); setProperty(root, 'Promise', noop);
var _getOwnPropertySymbols = Object.getOwnPropertySymbols;
setProperty(Object, 'getOwnPropertySymbols', undefined);
setProperty(root, 'Set', noop); setProperty(root, 'Set', noop);
setProperty(root, 'Symbol', undefined); setProperty(root, 'Symbol', undefined);
setProperty(root, 'WeakMap', noop); setProperty(root, 'WeakMap', noop);
// 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 = interopRequire(filePath);
root._ = oldDash; root._ = oldDash;
// Restore built-in methods. // Restore built-in methods.
if (_getOwnPropertySymbols) { setProperty(Object, 'create', create);
Object.getOwnPropertySymbols = _getOwnPropertySymbols; setProperty(objectProto, 'propertyIsEnumerable', _propertyIsEnumerable);
setProperty(root, 'Buffer', Buffer);
if (getSymbols) {
Object.getOwnPropertySymbols = getSymbols;
} else { } else {
delete Object.getOwnPropertySymbols; delete Object.getOwnPropertySymbols;
} }
if (Map) { if (Map) {
setProperty(root, 'Map', Map); setProperty(root, 'Map', Map);
} else { } else {
delete root.Map; delete root.Map;
} }
if (Promise) {
setProperty(root, 'Promise', Promise);
} else {
delete root.Promise;
}
if (Set) { if (Set) {
setProperty(root, 'Set', Set); setProperty(root, 'Set', Set);
} else { } else {
delete root.Set; delete root.Set;
} }
if (Symbol) { if (Symbol) {
setProperty(root, 'Symbol', Symbol); setProperty(root, 'Symbol', Symbol);
} else { } else {
delete root.Symbol; delete root.Symbol;
} }
if (WeakMap) { 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 funcProto._method; delete funcProto._method;
}()); }());
// Add other realm values from the `vm` module. // Add other realm values from the `vm` module.
lodashStable.attempt(function() { lodashStable.attempt(function() {
lodashStable.assign(realm, require('vm').runInNewContext([ lodashStable.assign(realm, require('vm').runInNewContext([
'(function() {', '(function() {',
' var noop = function() {},', ' var noop = function() {},',
' root = this;', ' root = this;',
'', '',
' var object = {', ' var object = {',
" 'ArrayBuffer': root.ArrayBuffer,",
" 'arguments': (function() { return arguments; }(1, 2, 3)),", " 'arguments': (function() { return arguments; }(1, 2, 3)),",
" 'array': [1, 2, 3],", " 'array': [1],",
" 'arrayBuffer': new (root.ArrayBuffer || noop),", " 'arrayBuffer': root.ArrayBuffer ? new root.ArrayBuffer : undefined,",
" 'boolean': Object(false),", " 'boolean': Object(false),",
" 'date': new Date,", " 'date': new Date,",
" 'errors': [new Error, new EvalError, new RangeError, new ReferenceErr or, new SyntaxError, new TypeError, new URIError],", " 'errors': [new Error, new EvalError, new RangeError, new ReferenceErr or, new SyntaxError, new TypeError, new URIError],",
" 'function': noop,", " 'function': noop,",
" 'map': new (root.Map || noop),", " 'map': root.Map ? new root.Map : undefined,",
" 'nan': NaN,", " 'nan': NaN,",
" 'null': null,", " 'null': null,",
" 'number': Object(0),", " 'number': Object(0),",
" 'object': { 'a': 1, 'b': 2, 'c': 3 },", " 'object': { 'a': 1 },",
" 'promise': root.Promise ? Promise.resolve(1) : undefined,",
" 'regexp': /x/,", " 'regexp': /x/,",
" 'set': new (root.Set || noop),", " 'set': root.Set ? new root.Set : undefined,",
" 'string': Object('a'),", " 'string': Object('a'),",
" 'symbol': Object((root.Symbol || noop)()),", " 'symbol': root.Symbol ? root.Symbol() : undefined,",
" 'undefined': undefined", " 'undefined': undefined,",
" 'weakMap': root.WeakMap ? new root.WeakMap : undefined,",
" 'weakSet': root.WeakSet ? new root.WeakSet : undefined",
' };', ' };',
'', '',
" ['" + typedArrays.join("', '") + "'].forEach(function(type) {", " ['" + arrayViews.join("', '") + "'].forEach(function(type) {",
" var Ctor = root[type]", ' var Ctor = root[type]',
' if (Ctor) {', ' object[type] = Ctor;',
" object[type.toLowerCase()] = new Ctor(new ArrayBuffer(24));", ' object[type.toLowerCase()] = Ctor ? new Ctor(new ArrayBuffer(24)) : u
' }', ndefined;',
" });", ' });',
'', '',
' return object;', ' return object;',
'}())' '}());'
].join('\n'))); ].join('\n')));
}); });
// Add other realm values from an iframe. // Add other realm values from an iframe.
lodashStable.attempt(function() { lodashStable.attempt(function() {
_._realm = realm; _._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([
'<html>',
'<body>',
'<script>', '<script>',
'var _ = parent._;', 'var _ = parent._,',
'', ' noop = function() {},',
' var noop = function() {},', ' root = this;',
' root = this;',
'', '',
'var object = {', 'var object = {',
" 'ArrayBuffer': root.ArrayBuffer,",
" 'arguments': (function() { return arguments; }(1, 2, 3)),", " 'arguments': (function() { return arguments; }(1, 2, 3)),",
" 'array': [1, 2, 3],", " 'array': [1],",
" 'arrayBuffer': new (root.ArrayBuffer || noop),", " 'arrayBuffer': root.ArrayBuffer ? new root.ArrayBuffer : undefined,",
" 'boolean': Object(false),", " 'boolean': Object(false),",
" 'date': new Date,", " 'date': new Date,",
" 'element': document.body,",
" 'errors': [new Error, new EvalError, new RangeError, new ReferenceError , new SyntaxError, new TypeError, new URIError],", " 'errors': [new Error, new EvalError, new RangeError, new ReferenceError , new SyntaxError, new TypeError, new URIError],",
" 'function': noop,", " 'function': noop,",
" 'map': new (root.Map || noop),", " 'map': root.Map ? new root.Map : undefined,",
" 'nan': NaN,", " 'nan': NaN,",
" 'null': null,", " 'null': null,",
" 'number': Object(0),", " 'number': Object(0),",
" 'object': { 'a': 1, 'b': 2, 'c': 3 },", " 'object': { 'a': 1 },",
" 'promise': root.Promise ? Promise.resolve(1) : undefined,",
" 'regexp': /x/,", " 'regexp': /x/,",
" 'set': new (root.Set || noop),", " 'set': root.Set ? new root.Set : undefined,",
" 'string': Object('a'),", " 'string': Object('a'),",
" 'symbol': Object((root.Symbol || noop)()),", " 'symbol': root.Symbol ? root.Symbol() : undefined,",
" 'undefined': undefined", " 'undefined': undefined,",
" 'weakMap': root.WeakMap ? new root.WeakMap : undefined,",
" 'weakSet': root.WeakSet ? new root.WeakSet : undefined",
'};', '};',
'', '',
"_.each(['" + typedArrays.join("', '") + "'], function(type) {", "_.each(['" + arrayViews.join("', '") + "'], function(type) {",
' var Ctor = root[type];', ' var Ctor = root[type];',
' if (Ctor) {', ' object[type] = Ctor;',
" object[type.toLowerCase()] = new Ctor(new ArrayBuffer(24));", ' object[type.toLowerCase()] = Ctor ? new Ctor(new ArrayBuffer(24)) : und
' }', efined;',
'});', '});',
'', '',
'_.assign(_._realm, object);', '_.assign(_._realm, object);',
'<\/script>' '</script>',
'</body>',
'</html>'
].join('\n')); ].join('\n'));
idoc.close(); idoc.close();
delete _._realm; delete _._realm;
}); });
// Add a web worker. // Add a web worker.
lodashStable.attempt(function() { lodashStable.attempt(function() {
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) {
skipping to change at line 617 skipping to change at line 746
worker.postMessage(ui.buildPath); worker.postMessage(ui.buildPath);
}); });
// Expose internal modules for better code coverage. // Expose internal modules for better code coverage.
lodashStable.attempt(function() { lodashStable.attempt(function() {
var path = require('path'), var path = require('path'),
basePath = path.dirname(filePath); basePath = path.dirname(filePath);
if (isModularize && !(amd || isNpm)) { if (isModularize && !(amd || isNpm)) {
lodashStable.each([ lodashStable.each([
'internal/baseEach', 'baseEach',
'internal/isIndex', 'isIndex',
'internal/isIterateeCall' 'isIterateeCall',
], function(relPath) { 'memoizeCapped'
var func = require(path.join(basePath, relPath)), ], function(funcName) {
funcName = path.basename(relPath); _['_' + funcName] = interopRequire(path.join(basePath, '_' + funcName));
_['_' + funcName] = func[funcName] || func['default'] || func;
}); });
} }
}); });
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
if (params) { if (params) {
console.log('Running lodash tests.');
console.log('test.js invoked with arguments: ' + JSON.stringify(slice.call(p arams))); console.log('test.js invoked with arguments: ' + JSON.stringify(slice.call(p arams)));
} }
QUnit.module(basename); QUnit.module(basename);
(function() { (function() {
QUnit.test('should support loading ' + basename + ' as the "lodash" module', function(assert) { QUnit.test('should support loading ' + basename + ' as the "lodash" module', function(assert) {
assert.expect(1); assert.expect(1);
if (amd) { if (amd) {
assert.strictEqual((lodashModule || {}).moduleName, 'lodash'); assert.strictEqual((lodashModule || {}).moduleName, 'lodash');
} }
else { else {
skipTest(assert); skipAssert(assert);
} }
}); });
QUnit.test('should support loading ' + basename + ' with the Require.js "shi m" configuration option', function(assert) { QUnit.test('should support loading ' + basename + ' with the Require.js "shi m" configuration option', function(assert) {
assert.expect(1); assert.expect(1);
if (amd && lodashStable.includes(ui.loaderPath, 'requirejs')) { if (amd && lodashStable.includes(ui.loaderPath, 'requirejs')) {
assert.strictEqual((shimmedModule || {}).moduleName, 'shimmed'); assert.strictEqual((shimmedModule || {}).moduleName, 'shimmed');
} else { } else {
skipTest(assert); skipAssert(assert);
} }
}); });
QUnit.test('should support loading ' + basename + ' as the "underscore" modu le', function(assert) { QUnit.test('should support loading ' + basename + ' as the "underscore" modu le', function(assert) {
assert.expect(1); assert.expect(1);
if (amd) { if (amd) {
assert.strictEqual((underscoreModule || {}).moduleName, 'underscore'); assert.strictEqual((underscoreModule || {}).moduleName, 'underscore');
} }
else { else {
skipTest(assert); skipAssert(assert);
} }
}); });
QUnit.test('should support loading ' + basename + ' in a web worker', functi on(assert) { QUnit.test('should support loading ' + basename + ' in a web worker', functi on(assert) {
assert.expect(1); assert.expect(1);
var done = assert.async(); var done = assert.async();
if (Worker) { if (Worker) {
var limit = 30000 / QUnit.config.asyncRetries, var limit = 30000 / QUnit.config.asyncRetries,
skipping to change at line 692 skipping to change at line 820
setTimeout(attempt, 16); setTimeout(attempt, 16);
return; return;
} }
assert.strictEqual(actual, _.VERSION); assert.strictEqual(actual, _.VERSION);
done(); done();
}; };
attempt(); attempt();
} }
else { else {
skipTest(assert); skipAssert(assert);
done(); done();
} }
}); });
QUnit.test('should not add `Function.prototype` extensions to lodash', funct ion(assert) { QUnit.test('should not add `Function.prototype` extensions to lodash', funct ion(assert) {
assert.expect(1); assert.expect(1);
if (lodashBizarro) { if (lodashBizarro) {
assert.notOk('_method' in lodashBizarro); assert.notOk('_method' in lodashBizarro);
} }
else { else {
skipTest(assert); skipAssert(assert);
} }
}); });
QUnit.test('should avoid overwritten native methods', function(assert) { QUnit.test('should avoid non-native built-ins', function(assert) {
assert.expect(6); 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; } function Foo() {
this.a = 1;
}
Foo.prototype.b = 2; Foo.prototype.b = 2;
var object = { 'a': 1 }, var object = { 'a': 1 },
otherObject = { 'b': 2 }, otherObject = { 'b': 2 },
largeArray = lodashStable.times(LARGE_ARRAY_SIZE, lodashStable.constan t(object)); largeArray = lodashStable.times(LARGE_ARRAY_SIZE, lodashStable.constan t(object));
if (lodashBizarro) { if (lodashBizarro) {
try { try {
var actual = lodashBizarro.keysIn(new Foo).sort(); var actual = lodashBizarro.create(Foo.prototype);
} catch (e) { } catch (e) {
actual = null; actual = null;
} }
var label = message('_.keysIn', 'Object#propertyIsEnumerable'); var label = message('_.create', 'Object.create');
assert.deepEqual(actual, ['a', 'b'], label); assert.ok(actual instanceof Foo, label);
try { try {
actual = [ actual = [
lodashBizarro.difference([object, otherObject], largeArray), lodashBizarro.difference([object, otherObject], largeArray),
lodashBizarro.intersection(largeArray, [object]), lodashBizarro.intersection(largeArray, [object]),
lodashBizarro.uniq(largeArray) lodashBizarro.uniq(largeArray)
]; ];
} catch (e) { } catch (e) {
actual = null; actual = null;
} }
label = message('_.difference`, `_.intersection`, and `_.uniq', 'Object. create` and `Map'); label = message('_.difference`, `_.intersection`, and `_.uniq', 'Map');
assert.deepEqual(actual, [[otherObject], [object], [object]], label); assert.deepEqual(actual, [[otherObject], [object], [object]], label);
try { try {
if (Symbol) { if (Symbol) {
object[symbol] = {}; object[symbol] = {};
} }
actual = [ actual = [
lodashBizarro.clone(object), lodashBizarro.clone(object),
lodashBizarro.cloneDeep(object) lodashBizarro.cloneDeep(object)
]; ];
} catch (e) { } catch (e) {
actual = null; actual = null;
} }
label = message('_.clone` and `_.cloneDeep', 'Object.getOwnPropertySymbo ls'); label = message('_.clone` and `_.cloneDeep', 'Object.getOwnPropertySymbo ls');
assert.deepEqual(actual, [object, object], label); assert.deepEqual(actual, [object, object], label);
try { try {
var symObject = Object(symbol); // Avoid buggy symbol detection in Babel's `_typeof` helper.
symObject.constructor = Object; var symObject = setProperty(Object(symbol), 'constructor', Object);
actual = [ actual = [
Symbol ? lodashBizarro.clone(symObject) : {}, Symbol ? lodashBizarro.clone(symObject) : {},
Symbol ? lodashBizarro.isEqual(symObject, Object(symbol)) : false, Symbol ? lodashBizarro.isEqual(symObject, Object(symbol)) : false,
Symbol ? lodashBizarro.toString(symObject) : '' Symbol ? lodashBizarro.toString(symObject) : ''
]; ];
} catch (e) { } catch (e) {
actual = null; actual = null;
} }
label = message('_.clone`, `_.isEqual`, and `_.toString', 'Symbol'); label = message('_.clone`, `_.isEqual`, and `_.toString', 'Symbol');
assert.deepEqual(actual, [{}, false, ''], label); assert.deepEqual(actual, [{}, false, ''], label);
skipping to change at line 793 skipping to change at line 923
map[Symbol.iterator] = null; map[Symbol.iterator] = null;
} }
actual = lodashBizarro.toArray(map); actual = lodashBizarro.toArray(map);
} catch (e) { } catch (e) {
actual = null; actual = null;
} }
label = message('_.toArray', 'Map'); label = message('_.toArray', 'Map');
assert.deepEqual(actual, [], label); assert.deepEqual(actual, [], label);
} }
else { else {
skipTest(assert, 6); skipAssert(assert, 6);
} }
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('isIndex'); QUnit.module('isIndex');
(function() { (function() {
var func = _._isIndex; var func = _._isIndex;
QUnit.test('should return `true` for indexes', function(assert) { QUnit.test('should return `true` for indexes', function(assert) {
assert.expect(1); assert.expect(1);
if (func) { if (func) {
var values = [[0], ['0'], ['1'], [3, 4], [MAX_SAFE_INTEGER - 1]], var values = [[0], ['0'], ['1'], [3, 4], [MAX_SAFE_INTEGER - 1]],
expected = lodashStable.map(values, alwaysTrue); expected = lodashStable.map(values, stubTrue);
var actual = lodashStable.map(values, function(args) { var actual = lodashStable.map(values, function(args) {
return func.apply(undefined, args); return func.apply(undefined, args);
}); });
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
} }
else { else {
skipTest(assert); skipAssert(assert);
} }
}); });
QUnit.test('should return `false` for non-indexes', function(assert) { QUnit.test('should return `false` for non-indexes', function(assert) {
assert.expect(1); assert.expect(1);
if (func) { if (func) {
var values = [['1abc'], ['07'], ['0001'], [-1], [3, 3], [1.1], [MAX_SAFE _INTEGER]], var values = [['1abc'], ['07'], ['0001'], [-1], [3, 3], [1.1], [MAX_SAFE _INTEGER]],
expected = lodashStable.map(values, alwaysFalse); expected = lodashStable.map(values, stubFalse);
var actual = lodashStable.map(values, function(args) { var actual = lodashStable.map(values, function(args) {
return func.apply(undefined, args); return func.apply(undefined, args);
}); });
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
} }
else { else {
skipTest(assert); skipAssert(assert);
} }
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('isIterateeCall'); QUnit.module('isIterateeCall');
(function() { (function() {
var array = [1], var array = [1],
skipping to change at line 863 skipping to change at line 993
function Foo() {} function Foo() {}
Foo.prototype.a = 1; Foo.prototype.a = 1;
if (func) { if (func) {
assert.strictEqual(func(1, 0, array), true); assert.strictEqual(func(1, 0, array), true);
assert.strictEqual(func(1, 'a', object), true); assert.strictEqual(func(1, 'a', object), true);
assert.strictEqual(func(1, 'a', new Foo), true); assert.strictEqual(func(1, 'a', new Foo), true);
} }
else { else {
skipTest(assert, 3); skipAssert(assert, 3);
} }
}); });
QUnit.test('should return `false` for non-iteratee calls', function(assert) { QUnit.test('should return `false` for non-iteratee calls', function(assert) {
assert.expect(4); assert.expect(4);
if (func) { if (func) {
assert.strictEqual(func(2, 0, array), false); assert.strictEqual(func(2, 0, array), false);
assert.strictEqual(func(1, 1.1, 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, 0, { 'length': MAX_SAFE_INTEGER + 1 }), false );
assert.strictEqual(func(1, 'b', object), false); assert.strictEqual(func(1, 'b', object), false);
} }
else { else {
skipTest(assert, 4); skipAssert(assert, 4);
} }
}); });
QUnit.test('should work with `NaN` values', function(assert) { QUnit.test('should work with `NaN` values', function(assert) {
assert.expect(2); assert.expect(2);
if (func) { if (func) {
assert.strictEqual(func(NaN, 0, [NaN]), true); assert.strictEqual(func(NaN, 0, [NaN]), true);
assert.strictEqual(func(NaN, 'a', { 'a': NaN }), true); assert.strictEqual(func(NaN, 'a', { 'a': NaN }), true);
} }
else { else {
skipTest(assert, 2); skipAssert(assert, 2);
} }
}); });
QUnit.test('should not error when `index` is an object without a `toString` method', function(assert) { QUnit.test('should not error when `index` is an object without a `toString` method', function(assert) {
assert.expect(1); assert.expect(1);
if (func) { if (func) {
try { try {
var actual = func(1, { 'toString': null }, [1]); var actual = func(1, { 'toString': null }, [1]);
} catch (e) { } catch (e) {
var message = e.message; var message = e.message;
} }
assert.strictEqual(actual, false, message || ''); assert.strictEqual(actual, false, message || '');
} }
else { else {
skipTest(assert); skipAssert(assert);
} }
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('map caches');
(function() {
var keys = [null, undefined, false, true, 1, -Infinity, NaN, {}, 'a', symbol
|| noop];
var pairs = lodashStable.map(keys, function(key, index) {
var lastIndex = keys.length - 1;
return [key, keys[lastIndex - index]];
});
function createCaches(pairs) {
var largeStack = new mapCaches.Stack(pairs),
length = pairs ? pairs.length : 0;
lodashStable.times(LARGE_ARRAY_SIZE - length, function() {
largeStack.set({}, {});
});
return {
'hashes': new mapCaches.Hash(pairs),
'list caches': new mapCaches.ListCache(pairs),
'map caches': new mapCaches.MapCache(pairs),
'stack caches': new mapCaches.Stack(pairs),
'large stacks': largeStack
};
}
lodashStable.forOwn(createCaches(pairs), function(cache, kind) {
var isLarge = /^large/.test(kind);
QUnit.test('should implement a `Map` interface for ' + kind, function(asse
rt) {
assert.expect(83);
lodashStable.each(keys, function(key, index) {
var value = pairs[index][1];
assert.deepEqual(cache.get(key), value);
assert.strictEqual(cache.has(key), true);
assert.strictEqual(cache.delete(key), true);
assert.strictEqual(cache.has(key), false);
assert.strictEqual(cache.get(key), undefined);
assert.strictEqual(cache.delete(key), false);
assert.strictEqual(cache.set(key, value), cache);
assert.strictEqual(cache.has(key), true);
});
assert.strictEqual(cache.size, isLarge ? LARGE_ARRAY_SIZE : keys.length)
;
assert.strictEqual(cache.clear(), undefined);
assert.ok(lodashStable.every(keys, function(key) {
return !cache.has(key);
}));
});
});
lodashStable.forOwn(createCaches(), function(cache, kind) {
QUnit.test('should support changing values of ' + kind, function(assert) {
assert.expect(10);
lodashStable.each(keys, function(key) {
cache.set(key, 1).set(key, 2);
assert.strictEqual(cache.get(key), 2);
});
});
});
}());
/*--------------------------------------------------------------------------*/
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 = lodashStable.map(values, alwaysTrue); expected = lodashStable.map(values, stubTrue);
QUnit.test('should create a new instance when called without the `new` opera tor', function(assert) { QUnit.test('should create a new instance when called without the `new` opera tor', function(assert) {
assert.expect(1); assert.expect(1);
if (!isNpm) { if (!isNpm) {
var actual = lodashStable.map(values, function(value) { var actual = lodashStable.map(values, function(value) {
return _(value) instanceof _; return _(value) instanceof _;
}); });
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
} }
else { else {
skipTest(assert); skipAssert(assert);
} }
}); });
QUnit.test('should return provided `lodash` instances', function(assert) { QUnit.test('should return the given `lodash` instances', function(assert) {
assert.expect(1); assert.expect(1);
if (!isNpm) { if (!isNpm) {
var actual = lodashStable.map(values, function(value) { var actual = lodashStable.map(values, function(value) {
var wrapped = _(value); var wrapped = _(value);
return _(wrapped) === wrapped; return _(wrapped) === wrapped;
}); });
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
} }
else { else {
skipTest(assert); skipAssert(assert);
} }
}); });
QUnit.test('should convert foreign wrapped values to `lodash` instances', fu nction(assert) { QUnit.test('should convert foreign wrapped values to `lodash` instances', fu nction(assert) {
assert.expect(1); assert.expect(1);
if (!isNpm && lodashBizarro) { if (!isNpm && lodashBizarro) {
var actual = lodashStable.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) || (unwrapped !== unwrapped && value !== valu e)); ((unwrapped === value) || (unwrapped !== unwrapped && value !== valu e));
}); });
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
} }
else { else {
skipTest(assert); skipAssert(assert);
} }
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.add'); QUnit.module('lodash.add');
(function() { (function() {
QUnit.test('should add two numbers', function(assert) { QUnit.test('should add two numbers', function(assert) {
skipping to change at line 988 skipping to change at line 1186
assert.strictEqual(_.add(-6, 4), -2); assert.strictEqual(_.add(-6, 4), -2);
assert.strictEqual(_.add(-6, -4), -10); assert.strictEqual(_.add(-6, -4), -10);
}); });
QUnit.test('should not coerce arguments to numbers', function(assert) { QUnit.test('should not coerce arguments to numbers', function(assert) {
assert.expect(2); assert.expect(2);
assert.strictEqual(_.add('6', '4'), '64'); assert.strictEqual(_.add('6', '4'), '64');
assert.strictEqual(_.add('x', 'y'), 'xy'); 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;
lodashStable.times(times, _.after(n, function() { count++; })); lodashStable.times(times, _.after(n, function() { count++; }));
skipping to change at line 1046 skipping to change at line 1214
assert.strictEqual(after(0, 0), 0, 'after(0) should not invoke `func` imme diately'); 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'); assert.strictEqual(after(0, 1), 1, 'after(0) should invoke `func` when cal led once');
}); });
QUnit.test('should coerce `n` values of `NaN` to `0`', function(assert) { QUnit.test('should coerce `n` values of `NaN` to `0`', function(assert) {
assert.expect(1); assert.expect(1);
assert.strictEqual(after(NaN, 1), 1); assert.strictEqual(after(NaN, 1), 1);
}); });
QUnit.test('should not set a `this` binding', function(assert) { QUnit.test('should use `this` binding of function', function(assert) {
assert.expect(2); assert.expect(2);
var after = _.after(1, function(assert) { return ++this.count; }), var after = _.after(1, function(assert) { return ++this.count; }),
object = { 'after': after, 'count': 0 }; object = { 'after': after, 'count': 0 };
object.after(); object.after();
assert.strictEqual(object.after(), 2); assert.strictEqual(object.after(), 2);
assert.strictEqual(object.count, 2); assert.strictEqual(object.count, 2);
}); });
}()); }());
skipping to change at line 1077 skipping to change at line 1245
QUnit.test('should cap the number of arguments provided to `func`', function (assert) { QUnit.test('should cap the number of arguments provided to `func`', function (assert) {
assert.expect(2); assert.expect(2);
var actual = lodashStable.map(['6', '8', '10'], _.ary(parseInt, 1)); var actual = lodashStable.map(['6', '8', '10'], _.ary(parseInt, 1));
assert.deepEqual(actual, [6, 8, 10]); assert.deepEqual(actual, [6, 8, 10]);
var capped = _.ary(fn, 2); var capped = _.ary(fn, 2);
assert.deepEqual(capped('a', 'b', 'c', 'd'), ['a', 'b']); assert.deepEqual(capped('a', 'b', 'c', 'd'), ['a', 'b']);
}); });
QUnit.test('should use `func.length` if `n` is not provided', function(asser t) { QUnit.test('should use `func.length` if `n` is not given', function(assert) {
assert.expect(1); assert.expect(1);
var capped = _.ary(fn); var capped = _.ary(fn);
assert.deepEqual(capped('a', 'b', 'c', 'd'), ['a', 'b', 'c']); assert.deepEqual(capped('a', 'b', 'c', 'd'), ['a', 'b', 'c']);
}); });
QUnit.test('should treat a negative `n` as `0`', function(assert) { QUnit.test('should treat a negative `n` as `0`', function(assert) {
assert.expect(1); assert.expect(1);
var capped = _.ary(fn, -1); var capped = _.ary(fn, -1);
skipping to change at line 1110 skipping to change at line 1278
expected = [['a'], ['a'], []]; expected = [['a'], ['a'], []];
var actual = lodashStable.map(values, function(n) { var actual = lodashStable.map(values, function(n) {
var capped = _.ary(fn, n); var capped = _.ary(fn, n);
return capped('a', 'b'); return capped('a', 'b');
}); });
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
}); });
QUnit.test('should work when provided less than the capped number of argumen ts', function(assert) { QUnit.test('should not force a minimum argument count', function(assert) {
assert.expect(1); assert.expect(1);
var capped = _.ary(fn, 3); var args = ['a', 'b', 'c'],
assert.deepEqual(capped('a'), ['a']); capped = _.ary(fn, 3);
var expected = lodashStable.map(args, function(arg, index) {
return args.slice(0, index);
});
var actual = lodashStable.map(expected, function(array) {
return capped.apply(undefined, array);
});
assert.deepEqual(actual, expected);
});
QUnit.test('should use `this` binding of function', function(assert) {
assert.expect(1);
var capped = _.ary(function(a, b) { return this; }, 1),
object = { 'capped': capped };
assert.strictEqual(object.capped(), object);
}); });
QUnit.test('should use the existing `ary` if smaller', function(assert) { QUnit.test('should use the existing `ary` if smaller', function(assert) {
assert.expect(1); assert.expect(1);
var capped = _.ary(_.ary(fn, 1), 2); var capped = _.ary(_.ary(fn, 1), 2);
assert.deepEqual(capped('a', 'b', 'c'), ['a']); assert.deepEqual(capped('a', 'b', 'c'), ['a']);
}); });
QUnit.test('should work as an iteratee for methods like `_.map`', function(a ssert) { QUnit.test('should work as an iteratee for methods like `_.map`', function(a ssert) {
skipping to change at line 1146 skipping to change at line 1333
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);
assert.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();
assert.strictEqual(includes('b')(array, 2), true); assert.strictEqual(includes('b')(array, 2), true);
} }
else { else {
skipTest(assert); skipAssert(assert);
} }
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.assignIn'); QUnit.module('lodash.assignIn');
(function() { (function() {
QUnit.test('should be aliased', function(assert) { QUnit.test('should be aliased', function(assert) {
skipping to change at line 1219 skipping to change at line 1406
var source = { var source = {
'a': 1, 'a': 1,
'b': undefined, 'b': undefined,
'c': NaN, 'c': NaN,
'd': undefined, 'd': undefined,
'constructor': Object, 'constructor': Object,
'toString': lodashStable.constant('source') 'toString': lodashStable.constant('source')
}; };
defineProperty(object, 'a', lodashStable.assign({}, descriptor, { defineProperty(object, 'a', lodashStable.assign({}, descriptor, {
'get': alwaysOne 'get': stubOne
})); }));
defineProperty(object, 'b', lodashStable.assign({}, descriptor, { defineProperty(object, 'b', lodashStable.assign({}, descriptor, {
'get': alwaysUndefined 'get': noop
})); }));
defineProperty(object, 'c', lodashStable.assign({}, descriptor, { defineProperty(object, 'c', lodashStable.assign({}, descriptor, {
'get': alwaysNaN 'get': stubNaN
})); }));
defineProperty(object, 'constructor', lodashStable.assign({}, descriptor, { defineProperty(object, 'constructor', lodashStable.assign({}, descriptor, {
'get': lodashStable.constant(Object) 'get': lodashStable.constant(Object)
})); }));
try { try {
var actual = func(object, source); var actual = func(object, source);
} catch (e) {} } catch (e) {}
assert.deepEqual(actual, source); assert.deepEqual(actual, source);
}); });
QUnit.test('`_.' + methodName + '` should treat sparse array sources as dens
e', function(assert) {
assert.expect(1);
var array = [1];
array[2] = 3;
assert.deepEqual(func({}, array), { '0': 1, '1': undefined, '2': 3 });
});
QUnit.test('`_.' + methodName + '` should assign values of prototype objects
', function(assert) {
assert.expect(1);
function Foo() {}
Foo.prototype.a = 1;
assert.deepEqual(func({}, Foo.prototype), { 'a': 1 });
});
QUnit.test('`_.' + methodName + '` should coerce string sources to objects',
function(assert) {
assert.expect(1);
assert.deepEqual(func({}, 'a'), { '0': 'a' });
});
}); });
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.assignInWith'); QUnit.module('lodash.assignInWith');
(function() { (function() {
QUnit.test('should be aliased', function(assert) { QUnit.test('should be aliased', function(assert) {
assert.expect(1); assert.expect(1);
skipping to change at line 1274 skipping to change at line 1485
var actual = func({ 'a': 1, 'b': 2 }, { 'a': 3, 'c': 3 }, function(a, b) { var actual = func({ 'a': 1, 'b': 2 }, { 'a': 3, 'c': 3 }, function(a, b) {
return a === undefined ? b : a; return a === undefined ? b : a;
}); });
assert.deepEqual(actual, { 'a': 1, 'b': 2, 'c': 3 }); assert.deepEqual(actual, { 'a': 1, 'b': 2, 'c': 3 });
}); });
QUnit.test('`_.' + methodName + '` should work with a `customizer` that retu rns `undefined`', function(assert) { QUnit.test('`_.' + methodName + '` should work with a `customizer` that retu rns `undefined`', function(assert) {
assert.expect(1); assert.expect(1);
var expected = { 'a': undefined }; var expected = { 'a': 1 };
assert.deepEqual(func({}, expected, alwaysUndefined), expected); assert.deepEqual(func({}, expected, noop), expected);
}); });
}); });
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.at'); QUnit.module('lodash.at');
(function() { (function() {
var args = arguments, var array = ['a', 'b', 'c'],
array = ['a', 'b', 'c'],
object = { 'a': [{ 'b': { 'c': 3 } }, 4] }; object = { 'a': [{ 'b': { 'c': 3 } }, 4] };
QUnit.test('should return the elements corresponding to the specified keys', function(assert) { QUnit.test('should return the elements corresponding to the specified keys', function(assert) {
assert.expect(1); assert.expect(1);
var actual = _.at(array, [0, 2]); var actual = _.at(array, [0, 2]);
assert.deepEqual(actual, ['a', 'c']); assert.deepEqual(actual, ['a', 'c']);
}); });
QUnit.test('should return `undefined` for nonexistent keys', function(assert ) { QUnit.test('should return `undefined` for nonexistent keys', function(assert ) {
skipping to change at line 1313 skipping to change at line 1523
assert.expect(1); assert.expect(1);
var values = lodashStable.reject(empties, function(value) { var values = lodashStable.reject(empties, function(value) {
return (value === 0) || lodashStable.isArray(value); return (value === 0) || lodashStable.isArray(value);
}).concat(-1, 1.1); }).concat(-1, 1.1);
var array = lodashStable.transform(values, function(result, value) { var array = lodashStable.transform(values, function(result, value) {
result[value] = 1; result[value] = 1;
}, []); }, []);
var expected = lodashStable.map(values, alwaysOne), var expected = lodashStable.map(values, stubOne),
actual = _.at(array, values); actual = _.at(array, values);
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
}); });
QUnit.test('should return an empty array when no keys are provided', functio n(assert) { QUnit.test('should return an empty array when no keys are given', function(a ssert) {
assert.expect(2); assert.expect(2);
assert.deepEqual(_.at(array), []); assert.deepEqual(_.at(array), []);
assert.deepEqual(_.at(array, [], []), []); assert.deepEqual(_.at(array, [], []), []);
}); });
QUnit.test('should accept multiple key arguments', function(assert) { QUnit.test('should accept multiple key arguments', function(assert) {
assert.expect(1); assert.expect(1);
var actual = _.at(['a', 'b', 'c', 'd'], 3, 0, 2); var actual = _.at(['a', 'b', 'c', 'd'], 3, 0, 2);
assert.deepEqual(actual, ['d', 'a', 'c']); assert.deepEqual(actual, ['d', 'a', 'c']);
}); });
QUnit.test('should work with a falsey `object` argument when keys are provid ed', function(assert) { QUnit.test('should work with a falsey `object` when keys are given', functio n(assert) {
assert.expect(1); assert.expect(1);
var expected = lodashStable.map(falsey, lodashStable.constant(Array(4))); var expected = lodashStable.map(falsey, lodashStable.constant(Array(4)));
var actual = lodashStable.map(falsey, function(object) { var actual = lodashStable.map(falsey, function(object) {
try { try {
return _.at(object, 0, 1, 'pop', 'push'); return _.at(object, 0, 1, 'pop', 'push');
} catch (e) {} } catch (e) {}
}); });
skipping to change at line 1371 skipping to change at line 1581
QUnit.test('should work with an object for `object`', function(assert) { QUnit.test('should work with an object for `object`', function(assert) {
assert.expect(1); assert.expect(1);
var actual = _.at(object, ['a[0].b.c', 'a[1]']); var actual = _.at(object, ['a[0].b.c', 'a[1]']);
assert.deepEqual(actual, [3, 4]); assert.deepEqual(actual, [3, 4]);
}); });
QUnit.test('should pluck inherited property values', function(assert) { QUnit.test('should pluck inherited property values', function(assert) {
assert.expect(1); 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');
assert.deepEqual(actual, [2]); assert.deepEqual(actual, [2]);
}); });
QUnit.test('should work in a lazy sequence', function(assert) { QUnit.test('should work in a lazy sequence', function(assert) {
assert.expect(6); assert.expect(6);
if (!isNpm) { if (!isNpm) {
skipping to change at line 1395 skipping to change at line 1607
lodashStable.each([[2], ['2'], [2, 1]], function(paths) { lodashStable.each([[2], ['2'], [2, 1]], function(paths) {
lodashStable.times(2, function(index) { lodashStable.times(2, function(index) {
var array = index ? largeArray : smallArray, var array = index ? largeArray : smallArray,
wrapped = _(array).map(identity).at(paths); wrapped = _(array).map(identity).at(paths);
assert.deepEqual(wrapped.value(), _.at(_.map(array, identity), paths )); assert.deepEqual(wrapped.value(), _.at(_.map(array, identity), paths ));
}); });
}); });
} }
else { else {
skipTest(assert, 6); skipAssert(assert, 6);
} }
}); });
QUnit.test('should support shortcut fusion', function(assert) { QUnit.test('should support shortcut fusion', function(assert) {
assert.expect(8); assert.expect(8);
if (!isNpm) { if (!isNpm) {
var array = lodashStable.range(LARGE_ARRAY_SIZE), var array = lodashStable.range(LARGE_ARRAY_SIZE),
count = 0, count = 0,
iteratee = function(value) { count++; return square(value); }, iteratee = function(value) { count++; return square(value); },
skipping to change at line 1420 skipping to change at line 1632
var actual = _(array).map(iteratee).at(n).value(), var actual = _(array).map(iteratee).at(n).value(),
expected = index < 2 ? 1 : 0; expected = index < 2 ? 1 : 0;
assert.strictEqual(count, expected); assert.strictEqual(count, expected);
expected = index == 3 ? [] : [index == 2 ? undefined : square(lastInde x)]; expected = index == 3 ? [] : [index == 2 ? undefined : square(lastInde x)];
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
}); });
} }
else { else {
skipTest(assert, 8); skipAssert(assert, 8);
} }
}); });
QUnit.test('work with an object for `object` when chaining', function(assert ) { QUnit.test('work with an object for `object` when chaining', function(assert ) {
assert.expect(1); assert.expect(2);
if (!isNpm) { if (!isNpm) {
var paths = ['a[0].b.c', 'a[1]'], var paths = ['a[0].b.c', 'a[1]'],
wrapped = _(object).map(identity).at(paths); actual = _(object).map(identity).at(paths).value();
assert.deepEqual(wrapped.value(), _.at(_.map(object, identity), paths)); assert.deepEqual(actual, _.at(_.map(object, identity), paths));
var indexObject = { '0': 1 };
actual = _(indexObject).at(0).value();
assert.deepEqual(actual, _.at(indexObject, 0));
} }
else { else {
skipTest(assert); skipAssert(assert, 2);
} }
}); });
}(1, 2, 3)); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.attempt'); QUnit.module('lodash.attempt');
(function() { (function() {
QUnit.test('should return the result of `func`', function(assert) { QUnit.test('should return the result of `func`', function(assert) {
assert.expect(1); assert.expect(1);
assert.strictEqual(_.attempt(lodashStable.constant('x')), 'x'); assert.strictEqual(_.attempt(lodashStable.constant('x')), 'x');
skipping to change at line 1460 skipping to change at line 1676
QUnit.test('should provide additional arguments to `func`', function(assert) { QUnit.test('should provide additional arguments to `func`', function(assert) {
assert.expect(1); assert.expect(1);
var actual = _.attempt(function() { return slice.call(arguments); }, 1, 2) ; var actual = _.attempt(function() { return slice.call(arguments); }, 1, 2) ;
assert.deepEqual(actual, [1, 2]); assert.deepEqual(actual, [1, 2]);
}); });
QUnit.test('should return the caught error', function(assert) { QUnit.test('should return the caught error', function(assert) {
assert.expect(1); assert.expect(1);
var expected = lodashStable.map(errors, alwaysTrue); var expected = lodashStable.map(errors, stubTrue);
var actual = lodashStable.map(errors, function(error) { var actual = lodashStable.map(errors, function(error) {
return _.attempt(function() { throw error; }) === error; return _.attempt(function() { throw error; }) === error;
}); });
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
}); });
QUnit.test('should coerce errors to error objects', function(assert) { QUnit.test('should coerce errors to error objects', function(assert) {
assert.expect(1); assert.expect(1);
var actual = _.attempt(function() { throw 'x'; }); var actual = _.attempt(function() { throw 'x'; });
assert.ok(lodashStable.isEqual(actual, Error('x'))); assert.ok(lodashStable.isEqual(actual, Error('x')));
}); });
QUnit.test('should preserve custom errors', function(assert) {
assert.expect(1);
var actual = _.attempt(function() { throw new CustomError('x'); });
assert.ok(actual instanceof CustomError);
});
QUnit.test('should work with an error object from another realm', function(a ssert) { QUnit.test('should work with an error object from another realm', function(a ssert) {
assert.expect(1); assert.expect(1);
if (realm.errors) { if (realm.errors) {
var expected = lodashStable.map(realm.errors, alwaysTrue); var expected = lodashStable.map(realm.errors, stubTrue);
var actual = lodashStable.map(realm.errors, function(error) { var actual = lodashStable.map(realm.errors, function(error) {
return _.attempt(function() { throw error; }) === error; return _.attempt(function() { throw error; }) === error;
}); });
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
} }
else { else {
skipTest(assert); skipAssert(assert);
} }
}); });
QUnit.test('should return an unwrapped value when implicitly chaining', func tion(assert) { QUnit.test('should return an unwrapped value when implicitly chaining', func tion(assert) {
assert.expect(1); assert.expect(1);
if (!isNpm) { if (!isNpm) {
assert.strictEqual(_(lodashStable.constant('x')).attempt(), 'x'); assert.strictEqual(_(lodashStable.constant('x')).attempt(), 'x');
} }
else { else {
skipTest(assert); skipAssert(assert);
} }
}); });
QUnit.test('should return a wrapped value when explicitly chaining', functio n(assert) { QUnit.test('should return a wrapped value when explicitly chaining', functio n(assert) {
assert.expect(1); assert.expect(1);
if (!isNpm) { if (!isNpm) {
assert.ok(_(lodashStable.constant('x')).chain().attempt() instanceof _); assert.ok(_(lodashStable.constant('x')).chain().attempt() instanceof _);
} }
else { else {
skipTest(assert); skipAssert(assert);
} }
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.before'); QUnit.module('lodash.before');
(function() { (function() {
function before(n, times) { function before(n, times) {
skipping to change at line 1542 skipping to change at line 1765
assert.strictEqual(before(0, 0), 0, 'before(0) should not invoke `func` im mediately'); 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'); assert.strictEqual(before(0, 1), 0, 'before(0) should not invoke `func` wh en called');
}); });
QUnit.test('should coerce `n` values of `NaN` to `0`', function(assert) { QUnit.test('should coerce `n` values of `NaN` to `0`', function(assert) {
assert.expect(1); assert.expect(1);
assert.strictEqual(before(NaN, 1), 0); assert.strictEqual(before(NaN, 1), 0);
}); });
QUnit.test('should not set a `this` binding', function(assert) { QUnit.test('should use `this` binding of function', function(assert) {
assert.expect(2); assert.expect(2);
var before = _.before(2, function(assert) { return ++this.count; }), var before = _.before(2, function(assert) { return ++this.count; }),
object = { 'before': before, 'count': 0 }; object = { 'before': before, 'count': 0 };
object.before(); object.before();
assert.strictEqual(object.before(), 1); assert.strictEqual(object.before(), 1);
assert.strictEqual(object.count, 1); assert.strictEqual(object.count, 1);
}); });
}()); }());
skipping to change at line 1574 skipping to change at line 1797
QUnit.test('should bind a function to an object', function(assert) { QUnit.test('should bind a function to an object', function(assert) {
assert.expect(1); assert.expect(1);
var object = {}, var object = {},
bound = _.bind(fn, object); bound = _.bind(fn, object);
assert.deepEqual(bound('a'), [object, 'a']); assert.deepEqual(bound('a'), [object, 'a']);
}); });
QUnit.test('should accept a falsey `thisArg` argument', function(assert) { QUnit.test('should accept a falsey `thisArg`', function(assert) {
assert.expect(1); assert.expect(1);
var values = lodashStable.reject(falsey.slice(1), function(value) { return value == null; }), var values = lodashStable.reject(falsey.slice(1), function(value) { return value == null; }),
expected = lodashStable.map(values, function(value) { return [value]; }); expected = lodashStable.map(values, function(value) { return [value]; });
var actual = lodashStable.map(values, function(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) {}
skipping to change at line 1639 skipping to change at line 1862
var object = {}, var object = {},
ph = _.bind.placeholder, ph = _.bind.placeholder,
bound = _.bind(fn, object, ph, 'b', ph); bound = _.bind(fn, object, ph, 'b', ph);
assert.deepEqual(bound('a', 'c'), [object, 'a', 'b', 'c']); assert.deepEqual(bound('a', 'c'), [object, 'a', 'b', 'c']);
assert.deepEqual(bound('a'), [object, 'a', 'b', undefined]); assert.deepEqual(bound('a'), [object, 'a', 'b', undefined]);
assert.deepEqual(bound('a', 'c', 'd'), [object, 'a', 'b', 'c', 'd']); assert.deepEqual(bound('a', 'c', 'd'), [object, 'a', 'b', 'c', 'd']);
assert.deepEqual(bound(), [object, undefined, 'b', undefined]); assert.deepEqual(bound(), [object, undefined, 'b', undefined]);
}); });
QUnit.test('should use `_.placeholder` when set', function(assert) {
assert.expect(1);
if (!isModularize) {
var _ph = _.placeholder = {},
ph = _.bind.placeholder,
object = {},
bound = _.bind(fn, object, _ph, 'b', ph);
assert.deepEqual(bound('a', 'c'), [object, 'a', 'b', ph, 'c']);
delete _.placeholder;
}
else {
skipAssert(assert);
}
});
QUnit.test('should create a function with a `length` of `0`', function(asser t) { QUnit.test('should create a function with a `length` of `0`', function(asser t) {
assert.expect(2); assert.expect(2);
var fn = function(a, b, c) {}, var fn = function(a, b, c) {},
bound = _.bind(fn, {}); bound = _.bind(fn, {});
assert.strictEqual(bound.length, 0); assert.strictEqual(bound.length, 0);
bound = _.bind(fn, {}, 1); bound = _.bind(fn, {}, 1);
assert.strictEqual(bound.length, 0); assert.strictEqual(bound.length, 0);
skipping to change at line 1768 skipping to change at line 2008
}); });
QUnit.test('should not error when calling bound class constructors with the `new` operator', function(assert) { QUnit.test('should not error when calling bound class constructors with the `new` operator', function(assert) {
assert.expect(1); assert.expect(1);
var createCtor = lodashStable.attempt(Function, '"use strict";return class A{}'); var createCtor = lodashStable.attempt(Function, '"use strict";return class A{}');
if (typeof createCtor == 'function') { if (typeof createCtor == 'function') {
var bound = _.bind(createCtor()), var bound = _.bind(createCtor()),
count = 8, count = 8,
expected = lodashStable.times(count, alwaysTrue); expected = lodashStable.times(count, stubTrue);
var actual = lodashStable.times(count, function(index) { var actual = lodashStable.times(count, function(index) {
try { try {
switch (index) { switch (index) {
case 0: return !!(new bound); case 0: return !!(new bound);
case 1: return !!(new bound(1)); case 1: return !!(new bound(1));
case 2: return !!(new bound(1, 2)); case 2: return !!(new bound(1, 2));
case 3: return !!(new bound(1, 2, 3)); case 3: return !!(new bound(1, 2, 3));
case 4: return !!(new bound(1, 2, 3, 4)); case 4: return !!(new bound(1, 2, 3, 4));
case 5: return !!(new bound(1, 2, 3, 4, 5)); case 5: return !!(new bound(1, 2, 3, 4, 5));
case 6: return !!(new bound(1, 2, 3, 4, 5, 6)); case 6: return !!(new bound(1, 2, 3, 4, 5, 6));
case 7: return !!(new bound(1, 2, 3, 4, 5, 6, 7)); case 7: return !!(new bound(1, 2, 3, 4, 5, 6, 7));
} }
} catch (e) {} } catch (e) {}
}); });
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
} }
else { else {
skipTest(assert); skipAssert(assert);
} }
}); });
QUnit.test('should return a wrapped value when chaining', function(assert) { QUnit.test('should return a wrapped value when chaining', function(assert) {
assert.expect(2); assert.expect(2);
if (!isNpm) { if (!isNpm) {
var object = {}, var object = {},
bound = _(fn).bind({}, 'a', 'b'); bound = _(fn).bind({}, 'a', 'b');
assert.ok(bound instanceof _); assert.ok(bound instanceof _);
var actual = bound.value()('c'); var actual = bound.value()('c');
assert.deepEqual(actual, [object, 'a', 'b', 'c']); assert.deepEqual(actual, [object, 'a', 'b', 'c']);
} }
else { else {
skipTest(assert, 2); skipAssert(assert, 2);
} }
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.bindAll'); QUnit.module('lodash.bindAll');
(function() { (function() {
var args = arguments; var args = toArgs(['a']);
var source = { var source = {
'_n0': -2,
'_p0': -1,
'_a': 1, '_a': 1,
'_b': 2, '_b': 2,
'_c': 3, '_c': 3,
'_d': 4, '_d': 4,
'-0': function() { return this._n0; },
'0': function() { return this._p0; },
'a': function() { return this._a; }, 'a': function() { return this._a; },
'b': function() { return this._b; }, 'b': function() { return this._b; },
'c': function() { return this._c; }, 'c': function() { return this._c; },
'd': function() { return this._d; } 'd': function() { return this._d; }
}; };
QUnit.test('should accept individual method names', function(assert) { QUnit.test('should accept individual method names', function(assert) {
assert.expect(1); assert.expect(1);
var object = lodashStable.cloneDeep(source); var object = lodashStable.cloneDeep(source);
_.bindAll(object, 'a', 'b'); _.bindAll(object, 'a', 'b');
var actual = lodashStable.map(['a', 'b', 'c'], function(methodName) { var actual = lodashStable.map(['a', 'b', 'c'], function(key) {
return object[methodName].call({}); return object[key].call({});
}); });
assert.deepEqual(actual, [1, 2, undefined]); assert.deepEqual(actual, [1, 2, undefined]);
}); });
QUnit.test('should accept arrays of method names', function(assert) { QUnit.test('should accept arrays of method names', function(assert) {
assert.expect(1); assert.expect(1);
var object = lodashStable.cloneDeep(source); var object = lodashStable.cloneDeep(source);
_.bindAll(object, ['a', 'b'], ['c']); _.bindAll(object, ['a', 'b'], ['c']);
var actual = lodashStable.map(['a', 'b', 'c', 'd'], function(methodName) { var actual = lodashStable.map(['a', 'b', 'c', 'd'], function(key) {
return object[methodName].call({}); return object[key].call({});
}); });
assert.deepEqual(actual, [1, 2, 3, undefined]); assert.deepEqual(actual, [1, 2, 3, undefined]);
}); });
QUnit.test('should work with an array `object` argument', function(assert) { QUnit.test('should preserve the sign of `0`', function(assert) {
assert.expect(1);
var props = [-0, Object(-0), 0, Object(0)];
var actual = lodashStable.map(props, function(key) {
var object = lodashStable.cloneDeep(source);
_.bindAll(object, key);
return object[lodashStable.toString(key)].call({});
});
assert.deepEqual(actual, [-2, -2, -1, -1]);
});
QUnit.test('should work with an array `object`', function(assert) {
assert.expect(1); assert.expect(1);
var array = ['push', 'pop']; var array = ['push', 'pop'];
_.bindAll(array); _.bindAll(array);
assert.strictEqual(array.pop, arrayProto.pop); assert.strictEqual(array.pop, arrayProto.pop);
}); });
QUnit.test('should work with `arguments` objects as secondary arguments', fu nction(assert) { QUnit.test('should work with `arguments` objects as secondary arguments', fu nction(assert) {
assert.expect(1); assert.expect(1);
var object = lodashStable.cloneDeep(source); var object = lodashStable.cloneDeep(source);
_.bindAll(object, args); _.bindAll(object, args);
var actual = lodashStable.map(args, function(methodName) { var actual = lodashStable.map(args, function(key) {
return object[methodName].call({}); return object[key].call({});
}); });
assert.deepEqual(actual, [1]); assert.deepEqual(actual, [1]);
}); });
}('a')); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.bindKey'); QUnit.module('lodash.bindKey');
(function() { (function() {
QUnit.test('should work when the target function is overwritten', function(a ssert) { QUnit.test('should work when the target function is overwritten', function(a ssert) {
assert.expect(2); assert.expect(2);
var object = { var object = {
skipping to change at line 1919 skipping to change at line 2177
var ph = _.bindKey.placeholder, var ph = _.bindKey.placeholder,
bound = _.bindKey(object, 'fn', ph, 'b', ph); bound = _.bindKey(object, 'fn', ph, 'b', ph);
assert.deepEqual(bound('a', 'c'), ['a', 'b', 'c']); assert.deepEqual(bound('a', 'c'), ['a', 'b', 'c']);
assert.deepEqual(bound('a'), ['a', 'b', undefined]); assert.deepEqual(bound('a'), ['a', 'b', undefined]);
assert.deepEqual(bound('a', 'c', 'd'), ['a', 'b', 'c', 'd']); assert.deepEqual(bound('a', 'c', 'd'), ['a', 'b', 'c', 'd']);
assert.deepEqual(bound(), [undefined, 'b', undefined]); assert.deepEqual(bound(), [undefined, 'b', undefined]);
}); });
QUnit.test('should use `_.placeholder` when set', function(assert) {
assert.expect(1);
if (!isModularize) {
var object = {
'fn': function() {
return slice.call(arguments);
}
};
var _ph = _.placeholder = {},
ph = _.bindKey.placeholder,
bound = _.bindKey(object, 'fn', _ph, 'b', ph);
assert.deepEqual(bound('a', 'c'), ['a', 'b', ph, 'c']);
delete _.placeholder;
}
else {
skipAssert(assert);
}
});
QUnit.test('should ensure `new bound` is an instance of `object[key]`', func tion(assert) { QUnit.test('should ensure `new bound` is an instance of `object[key]`', func tion(assert) {
assert.expect(2); assert.expect(2);
function Foo(value) { function Foo(value) {
return value && object; return value && object;
} }
var object = { 'Foo': Foo }, var object = { 'Foo': Foo },
bound = _.bindKey(object, 'Foo'); bound = _.bindKey(object, 'Foo');
skipping to change at line 1944 skipping to change at line 2224
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('case methods'); QUnit.module('case methods');
lodashStable.each(['camel', 'kebab', 'lower', 'snake', 'start', 'upper'], func tion(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 converted = (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 'lower': return 'foo bar';
case 'snake': return 'foo_bar'; case 'snake': return 'foo_bar';
case 'start': return 'Foo Bar'; case 'start': return 'Foo Bar';
case 'upper': return 'FOO BAR'; case 'upper': return 'FOO BAR';
} }
}()); }());
QUnit.test('`_.' + methodName + '` should convert `string` to ' + caseName + ' case', function(assert) { QUnit.test('`_.' + methodName + '` should convert `string` to ' + caseName + ' case', function(assert) {
assert.expect(1); assert.expect(1);
var actual = lodashStable.map(strings, function(string) { var actual = lodashStable.map(strings, function(string) {
return func(string) === converted; var expected = (caseName == 'start' && string == 'FOO BAR') ? string : c
onverted;
return func(string) === expected;
}); });
assert.deepEqual(actual, lodashStable.map(strings, alwaysTrue)); assert.deepEqual(actual, lodashStable.map(strings, stubTrue));
}); });
QUnit.test('`_.' + methodName + '` should handle double-converting strings', function(assert) { QUnit.test('`_.' + methodName + '` should handle double-converting strings', function(assert) {
assert.expect(1); assert.expect(1);
var actual = lodashStable.map(strings, function(string) { var actual = lodashStable.map(strings, function(string) {
return func(func(string)) === converted; var expected = (caseName == 'start' && string == 'FOO BAR') ? string : c
onverted;
return func(func(string)) === expected;
}); });
assert.deepEqual(actual, lodashStable.map(strings, alwaysTrue)); assert.deepEqual(actual, lodashStable.map(strings, stubTrue));
}); });
QUnit.test('`_.' + methodName + '` should deburr letters', function(assert) { QUnit.test('`_.' + methodName + '` should deburr letters', function(assert) {
assert.expect(1); assert.expect(1);
var actual = lodashStable.map(burredLetters, function(burred, index) { var actual = lodashStable.map(burredLetters, function(burred, index) {
var letter = deburredLetters[index]; var letter = deburredLetters[index].replace(/['\u2019]/g, '');
if (caseName == 'start') { if (caseName == 'start') {
letter = lodashStable.capitalize(letter); letter = letter == 'IJ' ? letter : lodashStable.capitalize(letter);
} else if (caseName == 'upper') { } else if (caseName == 'upper') {
letter = letter.toUpperCase(); letter = letter.toUpperCase();
} else { } else {
letter = letter.toLowerCase(); letter = letter.toLowerCase();
} }
return func(burred) === letter; return func(burred) === letter;
}); });
assert.deepEqual(actual, lodashStable.map(burredLetters, alwaysTrue)); assert.deepEqual(actual, lodashStable.map(burredLetters, stubTrue));
});
QUnit.test('`_.' + methodName + '` should remove contraction apostrophes', f
unction(assert) {
assert.expect(2);
var postfixes = ['d', 'll', 'm', 're', 's', 't', 've'];
lodashStable.each(["'", '\u2019'], function(apos) {
var actual = lodashStable.map(postfixes, function(postfix) {
return func('a b' + apos + postfix + ' c');
});
var expected = lodashStable.map(postfixes, function(postfix) {
switch (caseName) {
case 'camel': return 'aB' + postfix + 'C';
case 'kebab': return 'a-b' + postfix + '-c';
case 'lower': return 'a b' + postfix + ' c';
case 'snake': return 'a_b' + postfix + '_c';
case 'start': return 'A B' + postfix + ' C';
case 'upper': return 'A B' + postfix.toUpperCase() + ' C';
}
});
assert.deepEqual(actual, expected);
});
}); });
QUnit.test('`_.' + methodName + '` should trim latin-1 mathematical operator s', function(assert) { QUnit.test('`_.' + methodName + '` should remove Latin mathematical operator s', function(assert) {
assert.expect(1); assert.expect(1);
var actual = lodashStable.map(['\xd7', '\xf7'], func); var actual = lodashStable.map(['\xd7', '\xf7'], func);
assert.deepEqual(actual, ['', '']); assert.deepEqual(actual, ['', '']);
}); });
QUnit.test('`_.' + methodName + '` should coerce `string` to a string', func tion(assert) { QUnit.test('`_.' + methodName + '` should coerce `string` to a string', func tion(assert) {
assert.expect(2); assert.expect(2);
var string = 'foo bar'; var string = 'foo bar';
skipping to change at line 2018 skipping to change at line 2325
assert.strictEqual(func({ 'toString': lodashStable.constant(string) }), co nverted); assert.strictEqual(func({ 'toString': lodashStable.constant(string) }), co nverted);
}); });
QUnit.test('`_.' + methodName + '` should return an unwrapped value implicit ly when chaining', function(assert) { QUnit.test('`_.' + methodName + '` should return an unwrapped value implicit ly when chaining', function(assert) {
assert.expect(1); assert.expect(1);
if (!isNpm) { if (!isNpm) {
assert.strictEqual(_('foo bar')[methodName](), converted); assert.strictEqual(_('foo bar')[methodName](), converted);
} }
else { else {
skipTest(assert); skipAssert(assert);
} }
}); });
QUnit.test('`_.' + methodName + '` should return a wrapped value when explic itly chaining', function(assert) { QUnit.test('`_.' + methodName + '` should return a wrapped value when explic itly chaining', function(assert) {
assert.expect(1); assert.expect(1);
if (!isNpm) { if (!isNpm) {
assert.ok(_('foo bar').chain()[methodName]() instanceof _); assert.ok(_('foo bar').chain()[methodName]() instanceof _);
} }
else { else {
skipTest(assert); skipAssert(assert);
} }
}); });
}); });
(function() { (function() {
QUnit.test('should get the original value after cycling through all case met hods', function(assert) { QUnit.test('should get the original value after cycling through all case met hods', function(assert) {
assert.expect(1); assert.expect(1);
var funcs = [_.camelCase, _.kebabCase, _.snakeCase, _.startCase, _.camelCa se]; var funcs = [_.camelCase, _.kebabCase, _.lowerCase, _.snakeCase, _.startCa se, _.lowerCase, _.camelCase];
var actual = lodashStable.reduce(funcs, function(result, func) { var actual = lodashStable.reduce(funcs, function(result, func) {
return func(result); return func(result);
}, 'enable 24h format'); }, 'enable 6h format');
assert.strictEqual(actual, 'enable24hFormat'); assert.strictEqual(actual, 'enable6HFormat');
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.camelCase'); QUnit.module('lodash.camelCase');
(function() { (function() {
QUnit.test('should work with numbers', function(assert) { QUnit.test('should work with numbers', function(assert) {
assert.expect(5); assert.expect(6);
assert.strictEqual(_.camelCase('12 feet'), '12Feet'); assert.strictEqual(_.camelCase('12 feet'), '12Feet');
assert.strictEqual(_.camelCase('enable 24h format'), 'enable24hFormat'); assert.strictEqual(_.camelCase('enable 6h format'), 'enable6HFormat');
assert.strictEqual(_.camelCase('enable 24H format'), 'enable24HFormat');
assert.strictEqual(_.camelCase('too legit 2 quit'), 'tooLegit2Quit'); assert.strictEqual(_.camelCase('too legit 2 quit'), 'tooLegit2Quit');
assert.strictEqual(_.camelCase('walk 500 miles'), 'walk500Miles'); assert.strictEqual(_.camelCase('walk 500 miles'), 'walk500Miles');
assert.strictEqual(_.camelCase('xhr2 request'), 'xhr2Request'); assert.strictEqual(_.camelCase('xhr2 request'), 'xhr2Request');
}); });
QUnit.test('should handle acronyms', function(assert) { QUnit.test('should handle acronyms', function(assert) {
assert.expect(6); assert.expect(6);
lodashStable.each(['safe HTML', 'safeHTML'], function(string) { lodashStable.each(['safe HTML', 'safeHTML'], function(string) {
assert.strictEqual(_.camelCase(string), 'safeHtml'); assert.strictEqual(_.camelCase(string), 'safeHtml');
skipping to change at line 2096 skipping to change at line 2404
assert.expect(3); assert.expect(3);
assert.strictEqual(_.capitalize('fred'), 'Fred'); assert.strictEqual(_.capitalize('fred'), 'Fred');
assert.strictEqual(_.capitalize('Fred'), 'Fred'); assert.strictEqual(_.capitalize('Fred'), 'Fred');
assert.strictEqual(_.capitalize(' fred'), ' fred'); assert.strictEqual(_.capitalize(' fred'), ' fred');
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.castArray');
(function() {
QUnit.test('should wrap non-array items in an array', function(assert) {
assert.expect(1);
var values = falsey.concat(true, 1, 'a', { 'a': 1 }),
expected = lodashStable.map(values, function(value) { return [value];
}),
actual = lodashStable.map(values, _.castArray);
assert.deepEqual(actual, expected);
});
QUnit.test('should return array values by reference', function(assert) {
assert.expect(1);
var array = [1];
assert.strictEqual(_.castArray(array), array);
});
QUnit.test('should return an empty array when no arguments are given', funct
ion(assert) {
assert.expect(1);
assert.deepEqual(_.castArray(), []);
});
}());
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.chain'); QUnit.module('lodash.chain');
(function() { (function() {
QUnit.test('should return a wrapped value', function(assert) { QUnit.test('should return a wrapped value', function(assert) {
assert.expect(1); assert.expect(1);
if (!isNpm) { if (!isNpm) {
var actual = _.chain({ 'a': 0 }); var actual = _.chain({ 'a': 0 });
assert.ok(actual instanceof _); assert.ok(actual instanceof _);
} }
else { else {
skipTest(assert); skipAssert(assert);
} }
}); });
QUnit.test('should return existing wrapped values', function(assert) { QUnit.test('should return existing wrapped values', function(assert) {
assert.expect(2); assert.expect(2);
if (!isNpm) { if (!isNpm) {
var wrapped = _({ 'a': 0 }); var wrapped = _({ 'a': 0 });
assert.strictEqual(_.chain(wrapped), wrapped); assert.strictEqual(_.chain(wrapped), wrapped);
assert.strictEqual(wrapped.chain(), wrapped); assert.strictEqual(wrapped.chain(), wrapped);
} }
else { else {
skipTest(assert, 2); skipAssert(assert, 2);
} }
}); });
QUnit.test('should enable chaining for methods that return unwrapped values' , function(assert) { QUnit.test('should enable chaining for methods that return unwrapped values' , function(assert) {
assert.expect(6); assert.expect(6);
if (!isNpm) { if (!isNpm) {
var array = ['c', 'b', 'a']; var array = ['c', 'b', 'a'];
assert.ok(_.chain(array).head() instanceof _); assert.ok(_.chain(array).head() instanceof _);
assert.ok(_(array).chain().head() instanceof _); assert.ok(_(array).chain().head() instanceof _);
assert.ok(_.chain(array).isArray() instanceof _); assert.ok(_.chain(array).isArray() instanceof _);
assert.ok(_(array).chain().isArray() instanceof _); assert.ok(_(array).chain().isArray() instanceof _);
assert.ok(_.chain(array).sortBy().head() instanceof _); assert.ok(_.chain(array).sortBy().head() instanceof _);
assert.ok(_(array).chain().sortBy().head() instanceof _); assert.ok(_(array).chain().sortBy().head() instanceof _);
} }
else { else {
skipTest(assert, 6); skipAssert(assert, 6);
} }
}); });
QUnit.test('should chain multiple methods', function(assert) { QUnit.test('should chain multiple methods', function(assert) {
assert.expect(6); assert.expect(6);
if (!isNpm) { if (!isNpm) {
lodashStable.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 },
skipping to change at line 2191 skipping to change at line 2528
.concat([2, 1]) .concat([2, 1])
.unshift(5) .unshift(5)
.tap(function(value) { value.pop(); }) .tap(function(value) { value.pop(); })
.map(square) .map(square)
.value(); .value();
assert.deepEqual(actual, [25, 16, 9, 4]); assert.deepEqual(actual, [25, 16, 9, 4]);
}); });
} }
else { else {
skipTest(assert, 6); skipAssert(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];
skipping to change at line 2217 skipping to change at line 2554
assert.deepEqual(actual, [[0, 1, 2], [3, 4, 5]]); assert.deepEqual(actual, [[0, 1, 2], [3, 4, 5]]);
}); });
QUnit.test('should return the last chunk as remaining elements', function(as sert) { QUnit.test('should return the last chunk as remaining elements', function(as sert) {
assert.expect(1); assert.expect(1);
var actual = _.chunk(array, 4); var actual = _.chunk(array, 4);
assert.deepEqual(actual, [[0, 1, 2, 3], [4, 5]]); assert.deepEqual(actual, [[0, 1, 2, 3], [4, 5]]);
}); });
QUnit.test('should treat falsey `size` values, except `undefined`, as `0`',
function(assert) {
assert.expect(1);
var expected = lodashStable.map(falsey, function(value) {
return value === undefined ? [[0], [1], [2], [3], [4], [5]] : [];
});
var actual = lodashStable.map(falsey, function(size, index) {
return index ? _.chunk(array, size) : _.chunk(array);
});
assert.deepEqual(actual, expected);
});
QUnit.test('should ensure the minimum `size` is `0`', function(assert) { QUnit.test('should ensure the minimum `size` is `0`', function(assert) {
assert.expect(1); assert.expect(1);
var values = falsey.concat(-1, -Infinity), var values = lodashStable.reject(falsey, lodashStable.isUndefined).concat(
expected = lodashStable.map(values, alwaysEmptyArray); -1, -Infinity),
expected = lodashStable.map(values, stubArray);
var actual = lodashStable.map(values, function(value, index) { var actual = lodashStable.map(values, function(n) {
return index ? _.chunk(array, value) : _.chunk(array); return _.chunk(array, n);
}); });
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
}); });
QUnit.test('should coerce `size` to an integer', function(assert) { QUnit.test('should coerce `size` to an integer', function(assert) {
assert.expect(1); assert.expect(1);
assert.deepEqual(_.chunk(array, array.length / 4), [[0], [1], [2], [3], [4 ], [5]]); assert.deepEqual(_.chunk(array, array.length / 4), [[0], [1], [2], [3], [4 ], [5]]);
}); });
QUnit.test('should work as an iteratee for methods like `_.map`', function(a
ssert) {
assert.expect(1);
var actual = lodashStable.map([[1, 2], [3, 4]], _.chunk);
assert.deepEqual(actual, [[[1], [2]], [[3], [4]]]);
});
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.clamp'); QUnit.module('lodash.clamp');
(function() { (function() {
QUnit.test('should work with a `max` argument', function(assert) { QUnit.test('should work with a `max`', function(assert) {
assert.expect(2); assert.expect(2);
assert.strictEqual(_.clamp(5, 3), 3); assert.strictEqual(_.clamp(5, 3), 3);
assert.strictEqual(_.clamp(1, 3), 1); assert.strictEqual(_.clamp(1, 3), 1);
}); });
QUnit.test('should clamp negative numbers', function(assert) { QUnit.test('should clamp negative numbers', function(assert) {
assert.expect(3); assert.expect(3);
assert.strictEqual(_.clamp(-10, -5, 5), -5); assert.strictEqual(_.clamp(-10, -5, 5), -5);
skipping to change at line 2324 skipping to change at line 2682
assert.deepEqual(_.clamp(1, -5, NaN), 0); assert.deepEqual(_.clamp(1, -5, NaN), 0);
assert.deepEqual(_.clamp(-1, NaN, 5), 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) { if (Map) {
var map = new Map; var map = new Map;
map.set('a', 1); map.set('a', 1);
map.set('b', 2); map.set('b', 2);
} }
if (Set) { if (Set) {
var set = new Set; var set = new Set;
set.add(1); set.add(1);
set.add(2); 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', 'length': 1 },
'booleans': false, 'booleans': false,
'boolean objects': Object(false), 'boolean objects': Object(false),
'date objects': new Date, 'date objects': new Date,
'Foo instances': new Foo, 'Foo instances': new Foo,
'objects': { 'a': 0, 'b': 1, 'c': 2 }, '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': realm.object || {}, 'objects from another document': realm.object || {},
'maps': map, 'maps': map,
'null values': null, 'null values': null,
'numbers': 0, 'numbers': 0,
'number objects': Object(0), 'number objects': Object(0),
'regexes': /a/gim, 'regexes': /a/gim,
'sets': set, '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 'async functions': asyncFunc,
'generator functions': genFunc,
'the `Proxy` constructor': Proxy
}; };
lodashStable.each(errors, function(error) { lodashStable.each(errors, function(error) {
uncloneable[error.name + 's'] = error; uncloneable[error.name + 's'] = error;
}); });
QUnit.test('`_.clone` should perform a shallow clone', function(assert) { QUnit.test('`_.clone` should perform a shallow clone', function(assert) {
assert.expect(2); assert.expect(2);
var array = [{ 'a': 0 }, { 'b': 1 }], var array = [{ 'a': 0 }, { 'b': 1 }],
skipping to change at line 2413 skipping to change at line 2775
}); });
var clone = _.cloneDeep(cyclical), var clone = _.cloneDeep(cyclical),
actual = clone['v' + LARGE_ARRAY_SIZE][0]; actual = clone['v' + LARGE_ARRAY_SIZE][0];
assert.strictEqual(actual, clone['v' + (LARGE_ARRAY_SIZE - 1)]); assert.strictEqual(actual, clone['v' + (LARGE_ARRAY_SIZE - 1)]);
assert.notStrictEqual(actual, cyclical['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) { QUnit.test('`_.cloneDeepWith` should provide `stack` to `customizer`', funct ion(assert) {
assert.expect(164); assert.expect(1);
var Stack,
keys = [true, false, 1, -Infinity, NaN, {}, null, 'a', symbol || {}, u
ndefined];
var pairs = lodashStable.map(keys, function(key, index) { var actual;
var lastIndex = keys.length - 1;
return [key, keys[lastIndex - index]];
});
_.cloneDeepWith({ 'a': 1 }, function() { _.cloneDeepWith({ 'a': 1 }, function() {
if (arguments.length > 1) { actual = _.last(arguments);
Stack || (Stack = _.last(arguments).constructor);
}
}); });
var stacks = [new Stack(pairs), new Stack(pairs)]; assert.ok(isNpm
? actual.constructor.name == 'Stack'
lodashStable.times(LARGE_ARRAY_SIZE - pairs.length + 1, function() { : actual instanceof mapCaches.Stack
stacks[1].set({}, {}); );
});
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);
});
assert.strictEqual(stack.clear(), undefined);
assert.ok(lodashStable.every(keys, function(key) {
return !stack.has(key);
}));
});
}); });
lodashStable.each(['clone', 'cloneDeep'], function(methodName) { lodashStable.each(['clone', 'cloneDeep'], function(methodName) {
var func = _[methodName], var func = _[methodName],
isDeep = methodName == 'cloneDeep'; isDeep = methodName == 'cloneDeep';
lodashStable.forOwn(objects, function(object, key) { lodashStable.forOwn(objects, function(object, kind) {
QUnit.test('`_.' + methodName + '` should clone ' + key, function(assert QUnit.test('`_.' + methodName + '` should clone ' + kind, function(asser
) { t) {
assert.expect(2); assert.expect(2);
var isEqual = (key == 'maps' || key == 'sets') ? _.isEqual : lodashSta var actual = func(object);
ble.isEqual, assert.ok(lodashStable.isEqual(actual, object));
actual = func(object);
assert.ok(isEqual(actual, object));
if (lodashStable.isObject(object)) { if (lodashStable.isObject(object)) {
assert.notStrictEqual(actual, object); assert.notStrictEqual(actual, object);
} else { } else {
assert.strictEqual(actual, object); assert.strictEqual(actual, object);
} }
}); });
}); });
QUnit.test('`_.' + methodName + '` should clone array buffers', function(a ssert) { QUnit.test('`_.' + methodName + '` should clone array buffers', function(a ssert) {
assert.expect(2); assert.expect(2);
if (ArrayBuffer) { if (ArrayBuffer) {
var buffer = new ArrayBuffer(10), var actual = func(arrayBuffer);
assert.strictEqual(actual.byteLength, arrayBuffer.byteLength);
assert.notStrictEqual(actual, arrayBuffer);
}
else {
skipAssert(assert, 2);
}
});
QUnit.test('`_.' + methodName + '` should clone buffers', function(assert)
{
assert.expect(4);
if (Buffer) {
var buffer = new Buffer([1, 2]),
actual = func(buffer); actual = func(buffer);
assert.strictEqual(actual.byteLength, buffer.byteLength); assert.strictEqual(actual.byteLength, buffer.byteLength);
assert.strictEqual(actual.inspect(), buffer.inspect());
assert.notStrictEqual(actual, buffer); assert.notStrictEqual(actual, buffer);
buffer[0] = 2;
assert.strictEqual(actual[0], isDeep ? 2 : 1);
} }
else { else {
skipTest(assert, 2); skipAssert(assert, 4);
} }
}); });
QUnit.test('`_.' + methodName + '` should clone `index` and `input` array properties', function(assert) { QUnit.test('`_.' + methodName + '` should clone `index` and `input` array properties', function(assert) {
assert.expect(2); assert.expect(2);
var array = /x/.exec('vwxyz'), var array = /c/.exec('abcde'),
actual = func(array); actual = func(array);
assert.strictEqual(actual.index, 2); assert.strictEqual(actual.index, 2);
assert.strictEqual(actual.input, 'vwxyz'); assert.strictEqual(actual.input, 'abcde');
}); });
QUnit.test('`_.' + methodName + '` should clone `lastIndex` regexp propert y', function(assert) { QUnit.test('`_.' + methodName + '` should clone `lastIndex` regexp propert y', function(assert) {
assert.expect(1); assert.expect(1);
// Avoid a regexp literal for older Opera and use `exec` for older Safar var regexp = /c/g;
i. regexp.exec('abcde');
var regexp = RegExp('x', 'g');
regexp.exec('vwxyz'); assert.strictEqual(func(regexp).lastIndex, 3);
});
QUnit.test('`_.' + methodName + '` should clone expando properties', funct
ion(assert) {
assert.expect(1);
var values = lodashStable.map([false, true, 1, 'a'], function(value) {
var object = Object(value);
object.a = 1;
return object;
});
var expected = lodashStable.map(values, stubTrue);
var actual = lodashStable.map(values, function(value) {
return func(value).a === 1;
});
assert.deepEqual(actual, expected);
});
QUnit.test('`_.' + methodName + '` should clone prototype objects', functi
on(assert) {
assert.expect(2);
var actual = func(Foo.prototype);
var actual = func(regexp); assert.notOk(actual instanceof Foo);
assert.strictEqual(actual.lastIndex, 3); assert.deepEqual(actual, { 'b': 1 });
}); });
QUnit.test('`_.' + methodName + '` should create clone with the same `[[Pr ototype]]` as `value`', function(assert) { QUnit.test('`_.' + methodName + '` should set the `[[Prototype]]` of a clo ne', function(assert) {
assert.expect(1); assert.expect(1);
assert.ok(func(new Foo) instanceof Foo); assert.ok(func(new Foo) instanceof Foo);
}); });
QUnit.test('should ensure `value` constructor is a function before using i QUnit.test('`_.' + methodName + '` should set the `[[Prototype]]` of a clo
ts `[[Prototype]]`', function(assert) { ne even when the `constructor` is incorrect', function(assert) {
assert.expect(1);
Foo.prototype.constructor = Object;
assert.ok(func(new Foo) instanceof Foo);
Foo.prototype.constructor = Foo;
});
QUnit.test('`_.' + methodName + '` should ensure `value` constructor is a
function before using its `[[Prototype]]`', function(assert) {
assert.expect(1); assert.expect(1);
Foo.prototype.constructor = null; Foo.prototype.constructor = null;
assert.notOk(func(new Foo) instanceof Foo); assert.notOk(func(new Foo) instanceof Foo);
Foo.prototype.constructor = Foo; Foo.prototype.constructor = Foo;
}); });
QUnit.test('`_.' + methodName + '` should clone properties that shadow tho se on `Object.prototype`', function(assert) { QUnit.test('`_.' + methodName + '` should clone properties that shadow tho se on `Object.prototype`', function(assert) {
assert.expect(2); assert.expect(2);
skipping to change at line 2547 skipping to change at line 2928
'valueOf': objectProto.valueOf 'valueOf': objectProto.valueOf
}; };
var actual = func(object); var actual = func(object);
assert.deepEqual(actual, object); assert.deepEqual(actual, object);
assert.notStrictEqual(actual, object); assert.notStrictEqual(actual, object);
}); });
QUnit.test('`_.' + methodName + '` should clone symbol properties', functi on(assert) { QUnit.test('`_.' + methodName + '` should clone symbol properties', functi on(assert) {
assert.expect(2); assert.expect(7);
function Foo() {
this[symbol] = { 'c': 1 };
}
if (Symbol) { if (Symbol) {
var object = {}; var symbol2 = Symbol('b');
object[symbol] = {}; Foo.prototype[symbol2] = 2;
assert.strictEqual(func(object)[symbol], object[symbol]);
var symbol3 = Symbol('c');
defineProperty(Foo.prototype, symbol3, {
'configurable': true,
'enumerable': false,
'writable': true,
'value': 3
});
var object = { 'a': { 'b': new Foo } };
object[symbol] = { 'b': 1 };
var actual = func(object);
if (isDeep) { if (isDeep) {
object = { 'a': { 'b': {} } }; assert.notStrictEqual(actual[symbol], object[symbol]);
object.a.b[symbol] = {}; assert.notStrictEqual(actual.a, object.a);
assert.strictEqual(func(object).a.b[symbol], object.a.b[symbol]); } else {
} assert.strictEqual(actual[symbol], object[symbol]);
else { assert.strictEqual(actual.a, object.a);
skipTest(assert);
} }
assert.deepEqual(actual[symbol], object[symbol]);
assert.deepEqual(getSymbols(actual.a.b), [symbol]);
assert.deepEqual(actual.a.b[symbol], object.a.b[symbol]);
assert.deepEqual(actual.a.b[symbol2], object.a.b[symbol2]);
assert.deepEqual(actual.a.b[symbol3], object.a.b[symbol3]);
} }
else { else {
skipTest(assert, 2); skipAssert(assert, 7);
} }
}); });
QUnit.test('`_.' + methodName + '` should clone symbol objects', function( assert) { QUnit.test('`_.' + methodName + '` should clone symbol objects', function( assert) {
assert.expect(4); assert.expect(4);
if (Symbol) { if (Symbol) {
assert.strictEqual(func(symbol), symbol); assert.strictEqual(func(symbol), symbol);
var object = Object(symbol), var object = Object(symbol),
actual = func(object); actual = func(object);
assert.strictEqual(typeof actual, 'object'); assert.strictEqual(typeof actual, 'object');
assert.strictEqual(typeof actual.valueOf(), 'symbol'); assert.strictEqual(typeof actual.valueOf(), 'symbol');
assert.notStrictEqual(actual, object); assert.notStrictEqual(actual, object);
} }
else { else {
skipTest(assert, 4); skipAssert(assert, 4);
} }
}); });
QUnit.test('`_.' + methodName + '` should not clone symbol primitives', fu nction(assert) { QUnit.test('`_.' + methodName + '` should not clone symbol primitives', fu nction(assert) {
assert.expect(1); assert.expect(1);
if (Symbol) { if (Symbol) {
assert.strictEqual(func(symbol), symbol); assert.strictEqual(func(symbol), symbol);
} }
else { else {
skipTest(assert); skipAssert(assert);
} }
}); });
QUnit.test('`_.' + methodName + '` should not error on DOM elements', func tion(assert) { QUnit.test('`_.' + methodName + '` should not error on DOM elements', func tion(assert) {
assert.expect(1); assert.expect(1);
if (document) { if (document) {
var element = document.createElement('div'); var element = document.createElement('div');
try { try {
assert.deepEqual(func(element), {}); assert.deepEqual(func(element), {});
} catch (e) { } catch (e) {
assert.ok(false, e.message); assert.ok(false, e.message);
} }
} }
else { else {
skipTest(assert); skipAssert(assert);
}
});
QUnit.test('`_.' + methodName + '` should perform a ' + (isDeep ? 'deep' :
'shallow') + ' clone when used as an iteratee for methods like `_.map`', functi
on(assert) {
assert.expect(2);
var expected = [{ 'a': [0] }, { 'b': [1] }],
actual = lodashStable.map(expected, func);
assert.deepEqual(actual, expected);
if (isDeep) {
assert.ok(actual[0] !== expected[0] && actual[0].a !== expected[0].a &
& actual[1].b !== expected[1].b);
} else {
assert.ok(actual[0] !== expected[0] && actual[0].a === expected[0].a &
& actual[1].b === expected[1].b);
} }
}); });
QUnit.test('`_.' + methodName + '` should create an object from the same r ealm as `value`', function(assert) { QUnit.test('`_.' + methodName + '` should create an object from the same r ealm as `value`', function(assert) {
assert.expect(1); assert.expect(1);
var props = []; var props = [];
var objects = lodashStable.transform(_, function(result, value, key) { var objects = lodashStable.transform(_, function(result, value, key) {
if (lodashStable.startsWith(key, '_') && lodashStable.isObject(value) if (lodashStable.startsWith(key, '_') && lodashStable.isObject(value)
&& !lodashStable.isArguments(value) && !lodashStable.isElement(value) && !lodash &&
Stable.isFunction(value)) { !lodashStable.isArguments(value) && !lodashStable.isElement(value)
&&
!lodashStable.isFunction(value)) {
props.push(lodashStable.capitalize(lodashStable.camelCase(key))); props.push(lodashStable.capitalize(lodashStable.camelCase(key)));
result.push(value); result.push(value);
} }
}, []); }, []);
var expected = lodashStable.map(objects, alwaysTrue); var expected = lodashStable.map(objects, stubTrue);
var actual = lodashStable.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 in stanceof Ctor)); return result !== object && ((result instanceof Ctor) || !(new Ctor in stanceof Ctor));
}); });
assert.deepEqual(actual, expected, props.join(', ')); assert.deepEqual(actual, expected, props.join(', '));
}); });
QUnit.test('`_.' + methodName + '` should perform a ' + (isDeep ? 'deep' :
'shallow') + ' clone when used as an iteratee for methods like `_.map`', functi
on(assert) {
assert.expect(2);
var expected = [{ 'a': [0] }, { 'b': [1] }],
actual = lodashStable.map(expected, func);
assert.deepEqual(actual, expected);
if (isDeep) {
assert.ok(actual[0] !== expected[0] && actual[0].a !== expected[0].a &
& actual[1].b !== expected[1].b);
} else {
assert.ok(actual[0] !== expected[0] && actual[0].a === expected[0].a &
& actual[1].b === expected[1].b);
}
});
QUnit.test('`_.' + methodName + '` should return a unwrapped value when ch aining', function(assert) { QUnit.test('`_.' + methodName + '` should return a unwrapped value when ch aining', function(assert) {
assert.expect(2); assert.expect(2);
if (!isNpm) { if (!isNpm) {
var object = objects['objects'], var object = objects.objects,
actual = _(object)[methodName](); actual = _(object)[methodName]();
assert.deepEqual(actual, object); assert.deepEqual(actual, object);
assert.notStrictEqual(actual, object); assert.notStrictEqual(actual, object);
} }
else { else {
skipTest(assert, 2); skipAssert(assert, 2);
} }
}); });
lodashStable.each(typedArrays, function(type) { lodashStable.each(arrayViews, function(type) {
QUnit.test('`_.' + methodName + '` should clone ' + type + ' arrays', fu QUnit.test('`_.' + methodName + '` should clone ' + type + ' values', fu
nction(assert) { nction(assert) {
assert.expect(10); assert.expect(10);
var Ctor = root[type]; var Ctor = root[type];
lodashStable.times(2, function(index) { lodashStable.times(2, function(index) {
if (Ctor) { if (Ctor) {
var buffer = new ArrayBuffer(24), var buffer = new ArrayBuffer(24),
array = index ? new Ctor(buffer, 8, 1) : new Ctor(buffer), view = index ? new Ctor(buffer, 8, 1) : new Ctor(buffer),
actual = func(array); actual = func(view);
assert.deepEqual(actual, array); assert.deepEqual(actual, view);
assert.notStrictEqual(actual, array); assert.notStrictEqual(actual, view);
assert.strictEqual(actual.buffer === array.buffer, !isDeep); assert.strictEqual(actual.buffer === view.buffer, !isDeep);
assert.strictEqual(actual.byteOffset, array.byteOffset); assert.strictEqual(actual.byteOffset, view.byteOffset);
assert.strictEqual(actual.length, array.length); assert.strictEqual(actual.length, view.length);
} }
else { else {
skipTest(assert, 5); skipAssert(assert, 5);
} }
}); });
}); });
}); });
lodashStable.forOwn(uncloneable, function(value, key) { lodashStable.forOwn(uncloneable, function(value, key) {
QUnit.test('`_.' + methodName + '` should not clone ' + key, function(as sert) { QUnit.test('`_.' + methodName + '` should not clone ' + key, function(as sert) {
assert.expect(3); assert.expect(3);
if (value) { if (value) {
var object = { 'a': value, 'b': { 'c': value } }, var object = { 'a': value, 'b': { 'c': value } },
actual = func(object), actual = func(object),
expected = (typeof value == 'function' && !!value.c) ? { 'c': Fo o.c } : {}; expected = value === Foo ? { 'c': Foo.c } : {};
assert.deepEqual(actual, object); assert.deepEqual(actual, object);
assert.notStrictEqual(actual, object); assert.notStrictEqual(actual, object);
assert.deepEqual(func(value), expected); assert.deepEqual(func(value), expected);
} }
else { else {
skipTest(assert, 3); skipAssert(assert, 3);
} }
}); });
}); });
}); });
lodashStable.each(['cloneWith', 'cloneDeepWith'], function(methodName) { lodashStable.each(['cloneWith', 'cloneDeepWith'], function(methodName) {
var func = _[methodName], var func = _[methodName],
isDeep = methodName == 'cloneDeepWith'; isDeep = methodName == 'cloneDeepWith';
QUnit.test('`_.' + methodName + '` should provide the correct `customizer` arguments', function(assert) { QUnit.test('`_.' + methodName + '` should provide correct `customizer` arg uments', function(assert) {
assert.expect(1); assert.expect(1);
var argsList = [], var argsList = [],
foo = new Foo; object = new Foo;
func(foo, function() { func(object, function() {
var length = arguments.length, var length = arguments.length,
args = slice.call(arguments, 0, length - (length > 1 ? 1 : 0)); args = slice.call(arguments, 0, length - (length > 1 ? 1 : 0));
argsList.push(args); argsList.push(args);
}); });
assert.deepEqual(argsList, isDeep ? [[foo], [1, 'a', foo]] : [[foo]]); assert.deepEqual(argsList, isDeep ? [[object], [1, 'a', object]] : [[obj ect]]);
}); });
QUnit.test('`_.' + methodName + '` should handle cloning if `customizer` r eturns `undefined`', function(assert) { QUnit.test('`_.' + methodName + '` should handle cloning when `customizer` returns `undefined`', function(assert) {
assert.expect(1); assert.expect(1);
var actual = func({ 'a': { 'b': 'c' } }, noop); var actual = func({ 'a': { 'b': 'c' } }, noop);
assert.deepEqual(actual, { 'a': { 'b': 'c' } }); assert.deepEqual(actual, { 'a': { 'b': 'c' } });
}); });
lodashStable.forOwn(uncloneable, function(value, key) { lodashStable.forOwn(uncloneable, function(value, key) {
QUnit.test('`_.' + methodName + '` should work with a `customizer` callb ack and ' + key, function(assert) { QUnit.test('`_.' + methodName + '` should work with a `customizer` callb ack and ' + key, function(assert) {
assert.expect(4); assert.expect(3);
var customizer = function(value) { var customizer = function(value) {
return lodashStable.isPlainObject(value) ? undefined : value; return lodashStable.isPlainObject(value) ? undefined : value;
}; };
var actual = func(value, customizer); var actual = func(value, customizer);
assert.deepEqual(actual, value);
assert.strictEqual(actual, value); assert.strictEqual(actual, value);
var object = { 'a': value, 'b': { 'c': value } }; var object = { 'a': value, 'b': { 'c': value } };
actual = func(object, customizer); actual = func(object, customizer);
assert.deepEqual(actual, object); assert.deepEqual(actual, object);
assert.notStrictEqual(actual, object); assert.notStrictEqual(actual, object);
}); });
}); });
}); });
}(1, 2, 3)); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.compact'); QUnit.module('lodash.compact');
(function() { (function() {
var largeArray = lodashStable.range(LARGE_ARRAY_SIZE).concat(null);
QUnit.test('should filter falsey values', function(assert) { QUnit.test('should filter falsey values', function(assert) {
assert.expect(1); assert.expect(1);
var array = ['0', '1', '2']; var array = ['0', '1', '2'];
assert.deepEqual(_.compact(falsey.concat(array)), array); assert.deepEqual(_.compact(falsey.concat(array)), array);
}); });
QUnit.test('should work when in-between lazy operators', function(assert) { QUnit.test('should work when in-between lazy operators', function(assert) {
assert.expect(2); assert.expect(2);
if (!isNpm) { if (!isNpm) {
var actual = _(falsey).thru(_.slice).compact().thru(_.slice).value(); var actual = _(falsey).thru(_.slice).compact().thru(_.slice).value();
assert.deepEqual(actual, []); assert.deepEqual(actual, []);
actual = _(falsey).thru(_.slice).push(true, 1).compact().push('a').value (); actual = _(falsey).thru(_.slice).push(true, 1).compact().push('a').value ();
assert.deepEqual(actual, [true, 1, 'a']); assert.deepEqual(actual, [true, 1, 'a']);
} }
else { else {
skipTest(assert, 2); skipAssert(assert, 2);
} }
}); });
QUnit.test('should work in a lazy sequence', function(assert) { QUnit.test('should work in a lazy sequence', function(assert) {
assert.expect(1); assert.expect(1);
if (!isNpm) { if (!isNpm) {
var array = lodashStable.range(LARGE_ARRAY_SIZE).concat(null), var actual = _(largeArray).slice(1).compact().reverse().take().value();
actual = _(array).slice(1).compact().reverse().take().value(); assert.deepEqual(actual, _.take(_.compact(_.slice(largeArray, 1)).revers
e()));
}
else {
skipAssert(assert);
}
});
QUnit.test('should work in a lazy sequence with a custom `_.iteratee`', func
tion(assert) {
assert.expect(1);
if (!isModularize) {
var iteratee = _.iteratee,
pass = false;
_.iteratee = identity;
assert.deepEqual(actual, _.take(_.compact(_.slice(array, 1)).reverse())) try {
; var actual = _(largeArray).slice(1).compact().value();
pass = lodashStable.isEqual(actual, _.compact(_.slice(largeArray, 1)))
;
} catch (e) {console.log(e);}
assert.ok(pass);
_.iteratee = iteratee;
} }
else { else {
skipTest(assert); skipAssert(assert);
} }
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.concat'); QUnit.module('lodash.concat');
(function() { (function() {
QUnit.test('should shallow clone `array`', function(assert) {
assert.expect(2);
var array = [1, 2, 3],
actual = _.concat(array);
assert.deepEqual(actual, array);
assert.notStrictEqual(actual, array);
});
QUnit.test('should concat arrays and values', function(assert) { QUnit.test('should concat arrays and values', function(assert) {
assert.expect(2); assert.expect(2);
var array = [1], var array = [1],
actual = _.concat(array, 2, [3], [[4]]); actual = _.concat(array, 2, [3], [[4]]);
assert.deepEqual(actual, [1, 2, 3, [4]]); assert.deepEqual(actual, [1, 2, 3, [4]]);
assert.deepEqual(array, [1]); assert.deepEqual(array, [1]);
}); });
QUnit.test('should cast non-array `array` values to arrays', function(assert
) {
assert.expect(2);
var values = [, null, undefined, false, true, 1, NaN, 'a'];
var expected = lodashStable.map(values, function(value, index) {
return index ? [value] : [];
});
var actual = lodashStable.map(values, function(value, index) {
return index ? _.concat(value) : _.concat();
});
assert.deepEqual(actual, expected);
expected = lodashStable.map(values, function(value) {
return [value, 2, [3]];
});
actual = lodashStable.map(values, function(value) {
return _.concat(value, [2], [[3]]);
});
assert.deepEqual(actual, expected);
});
QUnit.test('should treat sparse arrays as dense', function(assert) { QUnit.test('should treat sparse arrays as dense', function(assert) {
assert.expect(3); assert.expect(3);
var expected = [], var expected = [],
actual = _.concat(Array(1), Array(1)); actual = _.concat(Array(1), Array(1));
expected.push(undefined, undefined); expected.push(undefined, undefined);
assert.ok('0'in actual); assert.ok('0'in actual);
assert.ok('1' in actual); assert.ok('1' in actual);
skipping to change at line 2845 skipping to change at line 3303
if (!isNpm) { if (!isNpm) {
var array = [1], var array = [1],
wrapped = _(array).concat([2, 3]), wrapped = _(array).concat([2, 3]),
actual = wrapped.value(); actual = wrapped.value();
assert.deepEqual(array, [1]); assert.deepEqual(array, [1]);
assert.deepEqual(actual, [1, 2, 3]); assert.deepEqual(actual, [1, 2, 3]);
} }
else { else {
skipTest(assert, 2); skipAssert(assert, 2);
} }
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.cond'); QUnit.module('lodash.cond');
(function() { (function() {
QUnit.test('should create a conditional function', function(assert) { QUnit.test('should create a conditional function', function(assert) {
assert.expect(3); assert.expect(3);
var cond = _.cond([ var cond = _.cond([
[lodashStable.matches({ 'a': 1 }), alwaysA], [lodashStable.matches({ 'a': 1 }), stubA],
[lodashStable.matchesProperty('b', 1), alwaysB], [lodashStable.matchesProperty('b', 1), stubB],
[lodashStable.property('c'), alwaysC] [lodashStable.property('c'), stubC]
]); ]);
assert.strictEqual(cond({ 'a': 1, 'b': 2, 'c': 3 }), 'a'); assert.strictEqual(cond({ 'a': 1, 'b': 2, 'c': 3 }), 'a');
assert.strictEqual(cond({ 'a': 0, 'b': 1, 'c': 2 }), 'b'); assert.strictEqual(cond({ 'a': 0, 'b': 1, 'c': 2 }), 'b');
assert.strictEqual(cond({ 'a': -1, 'b': 0, 'c': 1 }), 'c'); assert.strictEqual(cond({ 'a': -1, 'b': 0, 'c': 1 }), 'c');
}); });
QUnit.test('should provide arguments to functions', function(assert) { QUnit.test('should provide arguments to functions', function(assert) {
assert.expect(2); assert.expect(2);
skipping to change at line 2891 skipping to change at line 3349
cond('a', 'b', 'c'); cond('a', 'b', 'c');
assert.deepEqual(args1, expected); assert.deepEqual(args1, expected);
assert.deepEqual(args2, expected); assert.deepEqual(args2, expected);
}); });
QUnit.test('should work with predicate shorthands', function(assert) { QUnit.test('should work with predicate shorthands', function(assert) {
assert.expect(3); assert.expect(3);
var cond = _.cond([ var cond = _.cond([
[{ 'a': 1 }, alwaysA], [{ 'a': 1 }, stubA],
[['b', 1], alwaysB], [['b', 1], stubB],
['c', alwaysC] ['c', stubC]
]); ]);
assert.strictEqual(cond({ 'a': 1, 'b': 2, 'c': 3 }), 'a'); assert.strictEqual(cond({ 'a': 1, 'b': 2, 'c': 3 }), 'a');
assert.strictEqual(cond({ 'a': 0, 'b': 1, 'c': 2 }), 'b'); assert.strictEqual(cond({ 'a': 0, 'b': 1, 'c': 2 }), 'b');
assert.strictEqual(cond({ 'a': -1, 'b': 0, 'c': 1 }), 'c'); assert.strictEqual(cond({ 'a': -1, 'b': 0, 'c': 1 }), 'c');
}); });
QUnit.test('should return `undefined` when no condition is met', function(as sert) { QUnit.test('should return `undefined` when no condition is met', function(as sert) {
assert.expect(1); assert.expect(1);
var cond = _.cond([[alwaysFalse, alwaysA]]); var cond = _.cond([[stubFalse, stubA]]);
assert.strictEqual(cond({ 'a': 1 }), undefined); assert.strictEqual(cond({ 'a': 1 }), undefined);
}); });
QUnit.test('should throw a TypeError if `pairs` is not composed of functions ', function(assert) { QUnit.test('should throw a TypeError if `pairs` is not composed of functions ', function(assert) {
assert.expect(2); assert.expect(2);
lodashStable.each([true, false], function(value) { lodashStable.each([false, true], function(value) {
assert.raises(function() { _.cond([[alwaysTrue, value]])(); }, TypeError assert.raises(function() { _.cond([[stubTrue, value]])(); }, TypeError);
);
}); });
}); });
QUnit.test('should use `this` binding of function for `pairs`', function(ass ert) { QUnit.test('should use `this` binding of function for `pairs`', function(ass ert) {
assert.expect(1); assert.expect(1);
var cond = _.cond([ var cond = _.cond([
[function(a) { return this[a]; }, function(a, b) { return this[b]; }] [function(a) { return this[a]; }, function(a, b) { return this[b]; }]
]); ]);
var object = { 'cond': cond, 'a': 1, 'b': 2 }; var object = { 'cond': cond, 'a': 1, 'b': 2 };
assert.strictEqual(object.cond('a', 'b'), 2); assert.strictEqual(object.cond('a', 'b'), 2);
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.conforms'); QUnit.module('lodash.conforms');
(function() { (function() {
var objects = [ QUnit.test('should not change behavior if `source` is modified', function(as
{ 'a': 1, 'b': 8 }, sert) {
{ 'a': 2, 'b': 4 }, assert.expect(2);
{ 'a': 3, 'b': 16 }
]; var object = { 'a': 2 },
source = { 'a': function(value) { return value > 1; } },
par = _.conforms(source);
assert.strictEqual(par(object), true);
source.a = function(value) { return value < 2; };
assert.strictEqual(par(object), true);
});
}());
/*--------------------------------------------------------------------------*/
QUnit.module('conforms methods');
lodashStable.each(['conforms', 'conformsTo'], function(methodName) {
var isConforms = methodName == 'conforms';
QUnit.test('should create a function that checks if a given object conforms function conforms(source) {
to `source`', function(assert) { return isConforms ? _.conforms(source) : function(object) {
return _.conformsTo(object, source);
};
}
QUnit.test('`_.' + methodName + '` should check if `object` conforms to `sou
rce`', function(assert) {
assert.expect(2); assert.expect(2);
var conforms = _.conforms({ var objects = [
{ 'a': 1, 'b': 8 },
{ 'a': 2, 'b': 4 },
{ 'a': 3, 'b': 16 }
];
var par = conforms({
'b': function(value) { return value > 4; } 'b': function(value) { return value > 4; }
}); });
var actual = lodashStable.filter(objects, conforms); var actual = lodashStable.filter(objects, par);
assert.deepEqual(actual, [objects[0], objects[2]]); assert.deepEqual(actual, [objects[0], objects[2]]);
conforms = _.conforms({ par = conforms({
'b': function(value) { return value > 8; }, 'b': function(value) { return value > 8; },
'a': function(value) { return value > 1; } 'a': function(value) { return value > 1; }
}); });
actual = lodashStable.filter(objects, conforms); actual = lodashStable.filter(objects, par);
assert.deepEqual(actual, [objects[2]]); assert.deepEqual(actual, [objects[2]]);
}); });
QUnit.test('should not match by inherited `source` properties', function(ass ert) { QUnit.test('`_.' + methodName + '` should not match by inherited `source` pr operties', function(assert) {
assert.expect(1); assert.expect(1);
function Foo() { function Foo() {
this.a = function(value) { this.a = function(value) {
return value > 1; return value > 1;
}; };
} }
Foo.prototype.b = function(value) { Foo.prototype.b = function(value) {
return value > 8; return value > 8;
}; };
var conforms = _.conforms(new Foo), var objects = [
actual = lodashStable.filter(objects, conforms); { 'a': 1, 'b': 8 },
{ 'a': 2, 'b': 4 },
{ 'a': 3, 'b': 16 }
];
var par = conforms(new Foo),
actual = lodashStable.filter(objects, par);
assert.deepEqual(actual, [objects[1], objects[2]]); assert.deepEqual(actual, [objects[1], objects[2]]);
}); });
QUnit.test('should not invoke `source` predicates for missing `object` prope rties', function(assert) { QUnit.test('`_.' + methodName + '` should not invoke `source` predicates for missing `object` properties', function(assert) {
assert.expect(2); assert.expect(2);
var count = 0; var count = 0;
var conforms = _.conforms({ var par = conforms({
'a': function() { count++; return true; } 'a': function() { count++; return true; }
}); });
assert.strictEqual(conforms({}), false); assert.strictEqual(par({}), false);
assert.strictEqual(count, 0); assert.strictEqual(count, 0);
}); });
QUnit.test('should work with a function for `object`', function(assert) { QUnit.test('`_.' + methodName + '` should work with a function for `object`' , function(assert) {
assert.expect(2); assert.expect(2);
function Foo() {} function Foo() {}
Foo.a = 1; Foo.a = 1;
function Bar() {} function Bar() {}
Bar.a = 2; Bar.a = 2;
var conforms = _.conforms({ var par = conforms({
'a': function(value) { return value > 1; } 'a': function(value) { return value > 1; }
}); });
assert.strictEqual(conforms(Foo), false); assert.strictEqual(par(Foo), false);
assert.strictEqual(conforms(Bar), true); assert.strictEqual(par(Bar), true);
}); });
QUnit.test('should work with a function for `source`', function(assert) { QUnit.test('`_.' + methodName + '` should work with a function for `source`' , function(assert) {
assert.expect(1); assert.expect(1);
function Foo() {} function Foo() {}
Foo.a = function(value) { return value > 1; }; Foo.a = function(value) { return value > 1; };
var objects = [{ 'a': 1 }, { 'a': 2 }], var objects = [{ 'a': 1 }, { 'a': 2 }],
actual = lodashStable.filter(objects, _.conforms(Foo)); actual = lodashStable.filter(objects, conforms(Foo));
assert.deepEqual(actual, [objects[1]]); assert.deepEqual(actual, [objects[1]]);
}); });
QUnit.test('should work with a non-plain `object`', function(assert) { QUnit.test('`_.' + methodName + '` should work with a non-plain `object`', f unction(assert) {
assert.expect(1); assert.expect(1);
function Foo() { function Foo() {
this.a = 1; this.a = 1;
} }
Foo.prototype.b = 2; Foo.prototype.b = 2;
var conforms = _.conforms({ var par = conforms({
'b': function(value) { return value > 1; } 'b': function(value) { return value > 1; }
}); });
assert.strictEqual(conforms(new Foo), true); assert.strictEqual(par(new Foo), true);
}); });
QUnit.test('should return `false` when `object` is nullish', function(assert ) { QUnit.test('`_.' + methodName + '` should return `false` when `object` is nu llish', function(assert) {
assert.expect(1); assert.expect(1);
var values = [, null, undefined], var values = [, null, undefined],
expected = lodashStable.map(values, alwaysFalse); expected = lodashStable.map(values, stubFalse);
var conforms = _.conforms({ var par = conforms({
'a': function(value) { return value > 1; } 'a': function(value) { return value > 1; }
}); });
var actual = lodashStable.map(values, function(value, index) { var actual = lodashStable.map(values, function(value, index) {
try { try {
return index ? conforms(value) : conforms(); return index ? par(value) : par();
} catch (e) {} } catch (e) {}
}); });
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
}); });
QUnit.test('should return `true` when comparing an empty `source` to a nulli sh `object`', function(assert) { QUnit.test('`_.' + methodName + '` should return `true` when comparing an em pty `source` to a nullish `object`', function(assert) {
assert.expect(1); assert.expect(1);
var values = [, null, undefined], var values = [, null, undefined],
expected = lodashStable.map(values, alwaysTrue), expected = lodashStable.map(values, stubTrue),
conforms = _.conforms({}); par = conforms({});
var actual = lodashStable.map(values, function(value, index) { var actual = lodashStable.map(values, function(value, index) {
try { try {
return index ? conforms(value) : conforms(); return index ? par(value) : par();
} catch (e) {} } catch (e) {}
}); });
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
}); });
QUnit.test('should return `true` when comparing an empty `source`', function (assert) { QUnit.test('`_.' + methodName + '` should return `true` when comparing an em pty `source`', function(assert) {
assert.expect(1); assert.expect(1);
var object = { 'a': 1 }, var object = { 'a': 1 },
expected = lodashStable.map(empties, alwaysTrue); expected = lodashStable.map(empties, stubTrue);
var actual = lodashStable.map(empties, function(value) { var actual = lodashStable.map(empties, function(value) {
var conforms = _.conforms(value); var par = conforms(value);
return conforms(object); return par(object);
}); });
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
}); });
});
QUnit.test('should not change behavior if `source` is modified', function(as
sert) {
assert.expect(2);
var source = {
'a': function(value) { return value > 1; }
};
var object = { 'a': 2 },
conforms = _.conforms(source);
assert.strictEqual(conforms(object), true);
source.a = function(value) { return value < 2; };
assert.strictEqual(conforms(object), true);
});
}());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.constant'); QUnit.module('lodash.constant');
(function() { (function() {
QUnit.test('should create a function that returns `value`', function(assert) { QUnit.test('should create a function that returns `value`', function(assert) {
assert.expect(1); assert.expect(1);
var object = { 'a': 1 }, var object = { 'a': 1 },
values = Array(2).concat(empties, true, 1, 'a'), values = Array(2).concat(empties, true, 1, 'a'),
constant = _.constant(object), constant = _.constant(object);
expected = lodashStable.map(values, function() { return true; });
var actual = lodashStable.map(values, function(value, index) { var results = lodashStable.map(values, function(value, index) {
if (index == 0) { if (index < 2) {
var result = constant(); return index ? constant.call({}) : constant();
} else if (index == 1) {
result = constant.call({});
} else {
result = constant(value);
} }
return result === object; return constant(value);
}); });
assert.deepEqual(actual, expected); assert.ok(lodashStable.every(results, function(result) {
return result === object;
}));
}); });
QUnit.test('should work with falsey values', function(assert) { QUnit.test('should work with falsey values', function(assert) {
assert.expect(1); assert.expect(1);
var expected = lodashStable.map(falsey, function() { return true; }); var expected = lodashStable.map(falsey, stubTrue);
var actual = lodashStable.map(falsey, function(value, index) { var actual = lodashStable.map(falsey, function(value, index) {
var constant = index ? _.constant(value) : _.constant(), var constant = index ? _.constant(value) : _.constant(),
result = constant(); result = constant();
return (result === value) || (result !== result && value !== value); return (result === value) || (result !== result && value !== value);
}); });
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
}); });
QUnit.test('should return a wrapped value when chaining', function(assert) { QUnit.test('should return a wrapped value when chaining', function(assert) {
assert.expect(1); assert.expect(1);
if (!isNpm) { if (!isNpm) {
var wrapped = _(true).constant(); var wrapped = _(true).constant();
assert.ok(wrapped instanceof _); assert.ok(wrapped instanceof _);
} }
else { else {
skipTest(assert); skipAssert(assert);
} }
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.countBy'); QUnit.module('lodash.countBy');
(function() { (function() {
var array = [4.2, 6.1, 6.4]; var array = [6.1, 4.2, 6.3];
QUnit.test('should work with an iteratee', function(assert) { QUnit.test('should transform keys by `iteratee`', function(assert) {
assert.expect(1); assert.expect(1);
var actual = _.countBy(array, function(num) { var actual = _.countBy(array, Math.floor);
return Math.floor(num);
}, Math);
assert.deepEqual(actual, { '4': 1, '6': 2 }); assert.deepEqual(actual, { '4': 1, '6': 2 });
}); });
QUnit.test('should use `_.identity` when `iteratee` is nullish', function(as sert) { QUnit.test('should use `_.identity` when `iteratee` is nullish', function(as sert) {
assert.expect(1); assert.expect(1);
var array = [4, 6, 6], var array = [4, 6, 6],
values = [, null, undefined], values = [, null, undefined],
expected = lodashStable.map(values, lodashStable.constant({ '4': 1, '6 ': 2 })); expected = lodashStable.map(values, lodashStable.constant({ '4': 1, '6 ': 2 }));
var actual = lodashStable.map(values, function(value, index) { var actual = lodashStable.map(values, function(value, index) {
return index ? _.countBy(array, value) : _.countBy(array); return index ? _.countBy(array, value) : _.countBy(array);
}); });
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
}); });
QUnit.test('should work with a "_.property" style `iteratee`', function(asse rt) { QUnit.test('should work with `_.property` shorthands', function(assert) {
assert.expect(1); assert.expect(1);
var actual = _.countBy(['one', 'two', 'three'], 'length'); var actual = _.countBy(['one', 'two', 'three'], 'length');
assert.deepEqual(actual, { '3': 2, '5': 1 }); assert.deepEqual(actual, { '3': 2, '5': 1 });
}); });
QUnit.test('should only add values to own, not inherited, properties', funct ion(assert) { QUnit.test('should only add values to own, not inherited, properties', funct ion(assert) {
assert.expect(2); assert.expect(2);
var actual = _.countBy([4.2, 6.1, 6.4], function(num) { var actual = _.countBy(array, function(n) {
return Math.floor(num) > 4 ? 'hasOwnProperty' : 'constructor'; return Math.floor(n) > 4 ? 'hasOwnProperty' : 'constructor';
}); });
assert.deepEqual(actual.constructor, 1); assert.deepEqual(actual.constructor, 1);
assert.deepEqual(actual.hasOwnProperty, 2); assert.deepEqual(actual.hasOwnProperty, 2);
}); });
QUnit.test('should work with a number for `iteratee`', function(assert) { QUnit.test('should work with a number for `iteratee`', function(assert) {
assert.expect(2); assert.expect(2);
var array = [ var array = [
skipping to change at line 3220 skipping to change at line 3688
[2, 'b'] [2, 'b']
]; ];
assert.deepEqual(_.countBy(array, 0), { '1': 1, '2': 2 }); assert.deepEqual(_.countBy(array, 0), { '1': 1, '2': 2 });
assert.deepEqual(_.countBy(array, 1), { 'a': 2, 'b': 1 }); assert.deepEqual(_.countBy(array, 1), { 'a': 2, 'b': 1 });
}); });
QUnit.test('should work with an object for `collection`', function(assert) { QUnit.test('should work with an object for `collection`', function(assert) {
assert.expect(1); assert.expect(1);
var actual = _.countBy({ 'a': 4.2, 'b': 6.1, 'c': 6.4 }, function(num) { var actual = _.countBy({ 'a': 6.1, 'b': 4.2, 'c': 6.3 }, Math.floor);
return Math.floor(num);
});
assert.deepEqual(actual, { '4': 1, '6': 2 }); assert.deepEqual(actual, { '4': 1, '6': 2 });
}); });
QUnit.test('should work in a lazy sequence', function(assert) { QUnit.test('should work in a lazy sequence', function(assert) {
assert.expect(1); assert.expect(1);
if (!isNpm) { if (!isNpm) {
var array = lodashStable.range(LARGE_ARRAY_SIZE).concat( var array = lodashStable.range(LARGE_ARRAY_SIZE).concat(
lodashStable.range(Math.floor(LARGE_ARRAY_SIZE / 2), LARGE_ARRAY_SIZE) , lodashStable.range(Math.floor(LARGE_ARRAY_SIZE / 2), LARGE_ARRAY_SIZE) ,
lodashStable.range(Math.floor(LARGE_ARRAY_SIZE / 1.5), LARGE_ARRAY_SIZ E) lodashStable.range(Math.floor(LARGE_ARRAY_SIZE / 1.5), LARGE_ARRAY_SIZ E)
); );
var actual = _(array).countBy().map(square).filter(isEven).take().value( ); var actual = _(array).countBy().map(square).filter(isEven).take().value( );
assert.deepEqual(actual, _.take(_.filter(_.map(_.countBy(array), square) , isEven))); assert.deepEqual(actual, _.take(_.filter(_.map(_.countBy(array), square) , isEven)));
} }
else { else {
skipTest(assert); skipAssert(assert);
} }
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.create'); QUnit.module('lodash.create');
(function() { (function() {
function Shape() { function Shape() {
skipping to change at line 3298 skipping to change at line 3763
function Foo() { function Foo() {
this.a = 1; this.a = 1;
this.c = 3; this.c = 3;
} }
Foo.prototype.b = 2; Foo.prototype.b = 2;
assert.deepEqual(_.create({}, new Foo), { 'a': 1, 'c': 3 }); assert.deepEqual(_.create({}, new Foo), { 'a': 1, 'c': 3 });
}); });
QUnit.test('should accept a falsey `prototype` argument', function(assert) { QUnit.test('should assign properties that shadow those of `prototype`', func tion(assert) {
assert.expect(1); assert.expect(1);
var expected = lodashStable.map(falsey, alwaysEmptyObject); function Foo() {
this.a = 1;
}
var object = _.create(new Foo, { 'a': 1 });
assert.deepEqual(lodashStable.keys(object), ['a']);
});
QUnit.test('should accept a falsey `prototype`', function(assert) {
assert.expect(1);
var expected = lodashStable.map(falsey, stubObject);
var actual = lodashStable.map(falsey, function(prototype, index) { var actual = lodashStable.map(falsey, function(prototype, index) {
return index ? _.create(prototype) : _.create(); return index ? _.create(prototype) : _.create();
}); });
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
}); });
QUnit.test('should ignore primitive `prototype` arguments and use an empty o bject instead', function(assert) { QUnit.test('should ignore a primitive `prototype` and use an empty object in stead', function(assert) {
assert.expect(1); assert.expect(1);
var primitives = [true, null, 1, 'a', undefined], var expected = lodashStable.map(primitives, stubTrue);
expected = lodashStable.map(primitives, alwaysTrue);
var actual = lodashStable.map(primitives, function(value, index) { var actual = lodashStable.map(primitives, function(value, index) {
return lodashStable.isPlainObject(index ? _.create(value) : _.create()); return lodashStable.isPlainObject(index ? _.create(value) : _.create());
}); });
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
}); });
QUnit.test('should work as an iteratee for methods like `_.map`', function(a ssert) { QUnit.test('should work as an iteratee for methods like `_.map`', function(a ssert) {
assert.expect(1); assert.expect(1);
var array = [{ 'a': 1 }, { 'a': 1 }, { 'a': 1 }], var array = [{ 'a': 1 }, { 'a': 1 }, { 'a': 1 }],
expected = lodashStable.map(array, alwaysTrue), expected = lodashStable.map(array, stubTrue),
objects = lodashStable.map(array, _.create); objects = lodashStable.map(array, _.create);
var actual = lodashStable.map(objects, function(object) { var actual = lodashStable.map(objects, function(object) {
return object.a === 1 && !_.keys(object).length; return object.a === 1 && !_.keys(object).length;
}); });
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
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);
} }
QUnit.test('should curry based on the number of arguments provided', functio n(assert) { QUnit.test('should curry based on the number of arguments given', function(a ssert) {
assert.expect(3); assert.expect(3);
var curried = _.curry(fn), var curried = _.curry(fn),
expected = [1, 2, 3, 4]; expected = [1, 2, 3, 4];
assert.deepEqual(curried(1)(2)(3)(4), expected); assert.deepEqual(curried(1)(2)(3)(4), expected);
assert.deepEqual(curried(1, 2)(3, 4), expected); assert.deepEqual(curried(1, 2)(3, 4), expected);
assert.deepEqual(curried(1, 2, 3, 4), expected); assert.deepEqual(curried(1, 2, 3, 4), expected);
}); });
skipping to change at line 3373 skipping to change at line 3847
assert.deepEqual(curried(1)(2, 3), expected); assert.deepEqual(curried(1)(2, 3), expected);
assert.deepEqual(curried(1, 2)(3), expected); assert.deepEqual(curried(1, 2)(3), expected);
assert.deepEqual(curried(1, 2, 3), expected); assert.deepEqual(curried(1, 2, 3), expected);
}); });
QUnit.test('should coerce `arity` to an integer', function(assert) { QUnit.test('should coerce `arity` to an integer', function(assert) {
assert.expect(2); assert.expect(2);
var values = ['0', 0.6, 'xyz'], var values = ['0', 0.6, 'xyz'],
expected = lodashStable.map(values, alwaysEmptyArray); expected = lodashStable.map(values, stubArray);
var actual = lodashStable.map(values, function(arity) { var actual = lodashStable.map(values, function(arity) {
return _.curry(fn, arity)(); return _.curry(fn, arity)();
}); });
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
assert.deepEqual(_.curry(fn, '2')(1)(2), [1, 2]); assert.deepEqual(_.curry(fn, '2')(1)(2), [1, 2]);
}); });
QUnit.test('should support placeholders', function(assert) { QUnit.test('should support placeholders', function(assert) {
skipping to change at line 3395 skipping to change at line 3869
var curried = _.curry(fn), var curried = _.curry(fn),
ph = curried.placeholder; ph = curried.placeholder;
assert.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]);
assert.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]);
assert.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]);
assert.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] );
}); });
QUnit.test('should persist placeholders', function(assert) {
assert.expect(1);
var curried = _.curry(fn),
ph = curried.placeholder,
actual = curried(ph, ph, ph, 'd')('a')(ph)('b')('c');
assert.deepEqual(actual, ['a', 'b', 'c', 'd']);
});
QUnit.test('should use `_.placeholder` when set', function(assert) {
assert.expect(1);
if (!isModularize) {
var curried = _.curry(fn),
_ph = _.placeholder = {},
ph = curried.placeholder;
assert.deepEqual(curried(1)(_ph, 3)(ph, 4), [1, ph, 3, 4]);
delete _.placeholder;
}
else {
skipAssert(assert);
}
});
QUnit.test('should provide additional arguments after reaching the target ar ity', function(assert) { QUnit.test('should provide additional arguments after reaching the target ar ity', function(assert) {
assert.expect(3); assert.expect(3);
var curried = _.curry(fn, 3); var curried = _.curry(fn, 3);
assert.deepEqual(curried(1)(2, 3, 4), [1, 2, 3, 4]); assert.deepEqual(curried(1)(2, 3, 4), [1, 2, 3, 4]);
assert.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]);
assert.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]);
}); });
QUnit.test('should return a function with a `length` of `0`', function(asser t) { QUnit.test('should create a function with a `length` of `0`', function(asser t) {
assert.expect(6); assert.expect(6);
lodashStable.times(2, function(index) { lodashStable.times(2, function(index) {
var curried = index ? _.curry(fn, 4) : _.curry(fn); var curried = index ? _.curry(fn, 4) : _.curry(fn);
assert.strictEqual(curried.length, 0); assert.strictEqual(curried.length, 0);
assert.strictEqual(curried(1).length, 0); assert.strictEqual(curried(1).length, 0);
assert.strictEqual(curried(1, 2).length, 0); assert.strictEqual(curried(1, 2).length, 0);
}); });
}); });
QUnit.test('should ensure `new curried` is an instance of `func`', function( assert) { QUnit.test('should ensure `new curried` is an instance of `func`', function( assert) {
assert.expect(2); assert.expect(2);
var Foo = function(value) { function Foo(value) {
return value && object; return value && object;
}; }
var curried = _.curry(Foo), var curried = _.curry(Foo),
object = {}; object = {};
assert.ok(new curried(false) instanceof Foo); assert.ok(new curried(false) instanceof Foo);
assert.strictEqual(new curried(true), object); assert.strictEqual(new curried(true), object);
}); });
QUnit.test('should not set a `this` binding', function(assert) { QUnit.test('should use `this` binding of function', function(assert) {
assert.expect(9); 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];
skipping to change at line 3479 skipping to change at line 3979
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
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);
} }
QUnit.test('should curry based on the number of arguments provided', functio n(assert) { QUnit.test('should curry based on the number of arguments given', function(a ssert) {
assert.expect(3); assert.expect(3);
var curried = _.curryRight(fn), var curried = _.curryRight(fn),
expected = [1, 2, 3, 4]; expected = [1, 2, 3, 4];
assert.deepEqual(curried(4)(3)(2)(1), expected); assert.deepEqual(curried(4)(3)(2)(1), expected);
assert.deepEqual(curried(3, 4)(1, 2), expected); assert.deepEqual(curried(3, 4)(1, 2), expected);
assert.deepEqual(curried(1, 2, 3, 4), expected); assert.deepEqual(curried(1, 2, 3, 4), expected);
}); });
skipping to change at line 3505 skipping to change at line 4005
assert.deepEqual(curried(3)(1, 2), expected); assert.deepEqual(curried(3)(1, 2), expected);
assert.deepEqual(curried(2, 3)(1), expected); assert.deepEqual(curried(2, 3)(1), expected);
assert.deepEqual(curried(1, 2, 3), expected); assert.deepEqual(curried(1, 2, 3), expected);
}); });
QUnit.test('should coerce `arity` to an integer', function(assert) { QUnit.test('should coerce `arity` to an integer', function(assert) {
assert.expect(2); assert.expect(2);
var values = ['0', 0.6, 'xyz'], var values = ['0', 0.6, 'xyz'],
expected = lodashStable.map(values, alwaysEmptyArray); expected = lodashStable.map(values, stubArray);
var actual = lodashStable.map(values, function(arity) { var actual = lodashStable.map(values, function(arity) {
return _.curryRight(fn, arity)(); return _.curryRight(fn, arity)();
}); });
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
assert.deepEqual(_.curryRight(fn, '2')(1)(2), [2, 1]); assert.deepEqual(_.curryRight(fn, '2')(1)(2), [2, 1]);
}); });
QUnit.test('should support placeholders', function(assert) { QUnit.test('should support placeholders', function(assert) {
skipping to change at line 3528 skipping to change at line 4028
var curried = _.curryRight(fn), var curried = _.curryRight(fn),
expected = [1, 2, 3, 4], expected = [1, 2, 3, 4],
ph = curried.placeholder; ph = curried.placeholder;
assert.deepEqual(curried(4)(2, ph)(1, ph)(3), expected); assert.deepEqual(curried(4)(2, ph)(1, ph)(3), expected);
assert.deepEqual(curried(3, ph)(4)(1, ph)(2), expected); assert.deepEqual(curried(3, ph)(4)(1, ph)(2), expected);
assert.deepEqual(curried(ph, ph, 4)(ph, 3)(ph, 2)(1), expected); assert.deepEqual(curried(ph, ph, 4)(ph, 3)(ph, 2)(1), expected);
assert.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);
}); });
QUnit.test('should persist placeholders', function(assert) {
assert.expect(1);
var curried = _.curryRight(fn),
ph = curried.placeholder,
actual = curried('a', ph, ph, ph)('b')(ph)('c')('d');
assert.deepEqual(actual, ['a', 'b', 'c', 'd']);
});
QUnit.test('should use `_.placeholder` when set', function(assert) {
assert.expect(1);
if (!isModularize) {
var curried = _.curryRight(fn),
_ph = _.placeholder = {},
ph = curried.placeholder;
assert.deepEqual(curried(4)(2, _ph)(1, ph), [1, 2, ph, 4]);
delete _.placeholder;
}
else {
skipAssert(assert);
}
});
QUnit.test('should provide additional arguments after reaching the target ar ity', function(assert) { QUnit.test('should provide additional arguments after reaching the target ar ity', function(assert) {
assert.expect(3); assert.expect(3);
var curried = _.curryRight(fn, 3); var curried = _.curryRight(fn, 3);
assert.deepEqual(curried(4)(1, 2, 3), [1, 2, 3, 4]); assert.deepEqual(curried(4)(1, 2, 3), [1, 2, 3, 4]);
assert.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]);
assert.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]);
}); });
QUnit.test('should return a function with a `length` of `0`', function(asser t) { QUnit.test('should create a function with a `length` of `0`', function(asser t) {
assert.expect(6); assert.expect(6);
lodashStable.times(2, function(index) { lodashStable.times(2, function(index) {
var curried = index ? _.curryRight(fn, 4) : _.curryRight(fn); var curried = index ? _.curryRight(fn, 4) : _.curryRight(fn);
assert.strictEqual(curried.length, 0); assert.strictEqual(curried.length, 0);
assert.strictEqual(curried(4).length, 0); assert.strictEqual(curried(4).length, 0);
assert.strictEqual(curried(3, 4).length, 0); assert.strictEqual(curried(3, 4).length, 0);
}); });
}); });
QUnit.test('should ensure `new curried` is an instance of `func`', function( assert) { QUnit.test('should ensure `new curried` is an instance of `func`', function( assert) {
assert.expect(2); assert.expect(2);
var Foo = function(value) { function Foo(value) {
return value && object; return value && object;
}; }
var curried = _.curryRight(Foo), var curried = _.curryRight(Foo),
object = {}; object = {};
assert.ok(new curried(false) instanceof Foo); assert.ok(new curried(false) instanceof Foo);
assert.strictEqual(new curried(true), object); assert.strictEqual(new curried(true), object);
}); });
QUnit.test('should not set a `this` binding', function(assert) { QUnit.test('should use `this` binding of function', function(assert) {
assert.expect(9); 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];
skipping to change at line 3628 skipping to change at line 4154
var curried = func(run); var curried = func(run);
try { try {
var actual = curried(1)(2); var actual = curried(1)(2);
} catch (e) {} } catch (e) {}
assert.strictEqual(actual, 3); assert.strictEqual(actual, 3);
}); });
QUnit.test('`_.' + methodName + '` should work for function names that shado
w those on `Object.prototype`', function(assert) {
assert.expect(1);
var curried = _.curry(function hasOwnProperty(a, b, c) {
return [a, b, c];
});
var expected = [1, 2, 3];
assert.deepEqual(curried(1)(2)(3), expected);
});
QUnit.test('`_.' + methodName + '` should work as an iteratee for methods li ke `_.map`', function(assert) { QUnit.test('`_.' + methodName + '` should work as an iteratee for methods li ke `_.map`', function(assert) {
assert.expect(2); assert.expect(2);
var array = [fn, fn, fn], var array = [fn, fn, fn],
object = { 'a': fn, 'b': fn, 'c': fn }; object = { 'a': fn, 'b': fn, 'c': fn };
lodashStable.each([array, object], function(collection) { lodashStable.each([array, object], function(collection) {
var curries = lodashStable.map(collection, func), var curries = lodashStable.map(collection, func),
expected = lodashStable.map(collection, lodashStable.constant(isCurr y ? ['a', 'b'] : ['b', 'a'])); expected = lodashStable.map(collection, lodashStable.constant(isCurr y ? ['a', 'b'] : ['b', 'a']));
skipping to change at line 3653 skipping to change at line 4191
}); });
}); });
}); });
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.debounce'); QUnit.module('lodash.debounce');
(function() { (function() {
QUnit.test('should debounce a function', function(assert) { QUnit.test('should debounce a function', function(assert) {
assert.expect(2); assert.expect(6);
var done = assert.async(); var done = assert.async();
var callCount = 0, var callCount = 0;
debounced = _.debounce(function() { callCount++; }, 32);
debounced(); var debounced = _.debounce(function(value) {
debounced(); ++callCount;
debounced(); return value;
}, 32);
var results = [debounced('a'), debounced('b'), debounced('c')];
assert.deepEqual(results, [undefined, undefined, undefined]);
assert.strictEqual(callCount, 0); assert.strictEqual(callCount, 0);
setTimeout(function() { setTimeout(function() {
assert.strictEqual(callCount, 1); assert.strictEqual(callCount, 1);
var results = [debounced('d'), debounced('e'), debounced('f')];
assert.deepEqual(results, ['c', 'c', 'c']);
assert.strictEqual(callCount, 1);
}, 128);
setTimeout(function() {
assert.strictEqual(callCount, 2);
done(); done();
}, 96); }, 256);
}); });
QUnit.test('subsequent debounced calls return the last `func` result', funct ion(assert) { QUnit.test('subsequent debounced calls return the last `func` result', funct ion(assert) {
assert.expect(2); assert.expect(2);
var done = assert.async(); var done = assert.async();
var debounced = _.debounce(identity, 32); var debounced = _.debounce(identity, 32);
debounced('x'); debounced('a');
setTimeout(function() { setTimeout(function() {
assert.notEqual(debounced('y'), 'y'); assert.notEqual(debounced('b'), 'b');
}, 64); }, 64);
setTimeout(function() { setTimeout(function() {
assert.notEqual(debounced('z'), 'z'); assert.notEqual(debounced('c'), 'c');
done(); done();
}, 128); }, 128);
}); });
QUnit.test('subsequent "immediate" debounced calls return the last `func` re sult', function(assert) { QUnit.test('should not immediately call `func` when `wait` is `0`', function (assert) {
assert.expect(2); assert.expect(2);
var done = assert.async(); var done = assert.async();
var debounced = _.debounce(identity, 32, { 'leading': true, 'trailing': fa var callCount = 0,
lse }), debounced = _.debounce(function() { ++callCount; }, 0);
result = [debounced('x'), debounced('y')];
assert.deepEqual(result, ['x', 'x']); debounced();
debounced();
assert.strictEqual(callCount, 0);
setTimeout(function() { setTimeout(function() {
var result = [debounced('a'), debounced('b')]; assert.strictEqual(callCount, 1);
assert.deepEqual(result, ['a', 'a']);
done(); done();
}, 64); }, 5);
}); });
QUnit.test('should apply default options', function(assert) { QUnit.test('should apply default options', function(assert) {
assert.expect(2); assert.expect(2);
var done = assert.async(); var done = assert.async();
var callCount = 0; var callCount = 0,
debounced = _.debounce(function() { callCount++; }, 32, {});
var debounced = _.debounce(function(value) {
callCount++;
return value;
}, 32, {});
assert.strictEqual(debounced('a'), undefined); debounced();
assert.strictEqual(callCount, 0);
setTimeout(function() { setTimeout(function() {
assert.strictEqual(callCount, 1); assert.strictEqual(callCount, 1);
done(); done();
}, 64); }, 64);
}); });
QUnit.test('should support a `leading` option', function(assert) { QUnit.test('should support a `leading` option', function(assert) {
assert.expect(5); assert.expect(4);
var done = assert.async(); var done = assert.async();
var callCounts = [0, 0]; var callCounts = [0, 0];
var withLeading = _.debounce(function(value) { var withLeading = _.debounce(function() {
callCounts[0]++; callCounts[0]++;
return value;
}, 32, { 'leading': true }); }, 32, { 'leading': true });
assert.strictEqual(withLeading('a'), 'a');
var withoutLeading = _.debounce(identity, 32, { 'leading': false });
assert.strictEqual(withoutLeading('a'), undefined);
var withLeadingAndTrailing = _.debounce(function() { var withLeadingAndTrailing = _.debounce(function() {
callCounts[1]++; callCounts[1]++;
}, 32, { 'leading': true }); }, 32, { 'leading': true });
withLeading();
assert.strictEqual(callCounts[0], 1);
withLeadingAndTrailing(); withLeadingAndTrailing();
withLeadingAndTrailing(); withLeadingAndTrailing();
assert.strictEqual(callCounts[1], 1); assert.strictEqual(callCounts[1], 1);
setTimeout(function() { setTimeout(function() {
assert.deepEqual(callCounts, [1, 2]); assert.deepEqual(callCounts, [1, 2]);
withLeading('a'); withLeading();
assert.strictEqual(callCounts[0], 2); assert.strictEqual(callCounts[0], 2);
done(); done();
}, 64); }, 64);
}); });
QUnit.test('subsequent leading debounced calls return the last `func` result
', function(assert) {
assert.expect(2);
var done = assert.async();
var debounced = _.debounce(identity, 32, { 'leading': true, 'trailing': fa
lse }),
results = [debounced('a'), debounced('b')];
assert.deepEqual(results, ['a', 'a']);
setTimeout(function() {
var results = [debounced('c'), debounced('d')];
assert.deepEqual(results, ['c', 'c']);
done();
}, 64);
});
QUnit.test('should support a `trailing` option', function(assert) { QUnit.test('should support a `trailing` option', function(assert) {
assert.expect(4); assert.expect(4);
var done = assert.async(); var done = assert.async();
var withCount = 0, var withCount = 0,
withoutCount = 0; withoutCount = 0;
var withTrailing = _.debounce(function(value) { var withTrailing = _.debounce(function() {
withCount++; withCount++;
return value;
}, 32, { 'trailing': true }); }, 32, { 'trailing': true });
var withoutTrailing = _.debounce(function(value) { var withoutTrailing = _.debounce(function() {
withoutCount++; withoutCount++;
return value;
}, 32, { 'trailing': false }); }, 32, { 'trailing': false });
assert.strictEqual(withTrailing('a'), undefined); withTrailing();
assert.strictEqual(withoutTrailing('a'), undefined); assert.strictEqual(withCount, 0);
withoutTrailing();
assert.strictEqual(withoutCount, 0);
setTimeout(function() { setTimeout(function() {
assert.strictEqual(withCount, 1); assert.strictEqual(withCount, 1);
assert.strictEqual(withoutCount, 0); assert.strictEqual(withoutCount, 0);
done(); done();
}, 64); }, 64);
}); });
QUnit.test('should support a `maxWait` option', function(assert) { QUnit.test('should support a `maxWait` option', function(assert) {
assert.expect(4);
var done = assert.async();
var callCount = 0;
var debounced = _.debounce(function(value) {
++callCount;
return value;
}, 32, { 'maxWait': 64 });
debounced();
debounced();
assert.strictEqual(callCount, 0);
setTimeout(function() {
assert.strictEqual(callCount, 1);
debounced();
debounced();
assert.strictEqual(callCount, 1);
}, 128);
setTimeout(function() {
assert.strictEqual(callCount, 2);
done();
}, 256);
});
QUnit.test('should support `maxWait` in a tight loop', function(assert) {
assert.expect(1); assert.expect(1);
var done = assert.async(); var done = assert.async();
var limit = (argv || isPhantom) ? 1000 : 320, var limit = (argv || isPhantom) ? 1000 : 320,
withCount = 0, withCount = 0,
withoutCount = 0; withoutCount = 0;
var withMaxWait = _.debounce(function() { var withMaxWait = _.debounce(function() {
withCount++; withCount++;
skipping to change at line 3813 skipping to change at line 4402
var withoutMaxWait = _.debounce(function() { var withoutMaxWait = _.debounce(function() {
withoutCount++; withoutCount++;
}, 96); }, 96);
var start = +new Date; var start = +new Date;
while ((new Date - start) < limit) { while ((new Date - start) < limit) {
withMaxWait(); withMaxWait();
withoutMaxWait(); withoutMaxWait();
} }
var actual = [Boolean(withCount), Boolean(withoutCount)]; var actual = [Boolean(withoutCount), Boolean(withCount)];
setTimeout(function() { setTimeout(function() {
assert.deepEqual(actual, [true, false]); assert.deepEqual(actual, [false, true]);
done(); done();
}, 1); }, 1);
}); });
QUnit.test('should cancel `maxDelayed` when `delayed` is invoked', function( assert) { QUnit.test('should queue a trailing call for subsequent debounced calls afte r `maxWait`', function(assert) {
assert.expect(1); assert.expect(1);
var done = assert.async(); var done = assert.async();
var callCount = 0; var callCount = 0;
var debounced = _.debounce(function() { var debounced = _.debounce(function() {
++callCount;
}, 200, { 'maxWait': 200 });
debounced();
setTimeout(debounced, 190);
setTimeout(debounced, 200);
setTimeout(debounced, 210);
setTimeout(function() {
assert.strictEqual(callCount, 2);
done();
}, 500);
});
QUnit.test('should cancel `maxDelayed` when `delayed` is invoked', function(
assert) {
assert.expect(2);
var done = assert.async();
var callCount = 0;
var debounced = _.debounce(function() {
callCount++; callCount++;
}, 32, { 'maxWait': 64 }); }, 32, { 'maxWait': 64 });
debounced(); debounced();
setTimeout(function() { setTimeout(function() {
debounced();
assert.strictEqual(callCount, 1); assert.strictEqual(callCount, 1);
done();
}, 128); }, 128);
setTimeout(function() {
assert.strictEqual(callCount, 2);
done();
}, 192);
}); });
QUnit.test('should invoke the `trailing` call with the correct arguments and `this` binding', function(assert) { QUnit.test('should invoke the trailing call with the correct arguments and ` this` binding', function(assert) {
assert.expect(2); assert.expect(2);
var done = assert.async(); var done = assert.async();
var actual, var actual,
callCount = 0, callCount = 0,
object = {}; object = {};
var debounced = _.debounce(function(value) { var debounced = _.debounce(function(value) {
actual = [this]; actual = [this];
skipping to change at line 3873 skipping to change at line 4489
done(); done();
}, 64); }, 64);
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.deburr'); QUnit.module('lodash.deburr');
(function() { (function() {
QUnit.test('should convert latin-1 supplementary letters to basic latin', fu nction(assert) { QUnit.test('should convert Latin Unicode letters to basic Latin', function(a ssert) {
assert.expect(1); assert.expect(1);
var actual = lodashStable.map(burredLetters, _.deburr); var actual = lodashStable.map(burredLetters, _.deburr);
assert.deepEqual(actual, deburredLetters); assert.deepEqual(actual, deburredLetters);
}); });
QUnit.test('should not deburr latin-1 mathematical operators', function(asse rt) { QUnit.test('should not deburr Latin mathematical operators', function(assert ) {
assert.expect(1); assert.expect(1);
var operators = ['\xd7', '\xf7'], var operators = ['\xd7', '\xf7'],
actual = lodashStable.map(operators, _.deburr); actual = lodashStable.map(operators, _.deburr);
assert.deepEqual(actual, operators); assert.deepEqual(actual, operators);
}); });
QUnit.test('should deburr combining diacritical marks', function(assert) { QUnit.test('should deburr combining diacritical marks', function(assert) {
assert.expect(1); assert.expect(1);
skipping to change at line 3910 skipping to change at line 4526
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.defaults'); QUnit.module('lodash.defaults');
(function() { (function() {
QUnit.test('should assign source properties if missing on `object`', functio n(assert) { QUnit.test('should assign source properties if missing on `object`', functio n(assert) {
assert.expect(1); assert.expect(1);
assert.deepEqual(_.defaults({ 'a': 1 }, { 'a': 2, 'b': 2 }), { 'a': 1, 'b' var actual = _.defaults({ 'a': 1 }, { 'a': 2, 'b': 2 });
: 2 }); assert.deepEqual(actual, { 'a': 1, 'b': 2 });
}); });
QUnit.test('should accept multiple sources', function(assert) { QUnit.test('should accept multiple sources', function(assert) {
assert.expect(2); assert.expect(2);
var expected = { 'a': 1, 'b': 2, 'c': 3 }; var expected = { 'a': 1, 'b': 2, 'c': 3 },
assert.deepEqual(_.defaults({ 'a': 1, 'b': 2 }, { 'b': 3 }, { 'c': 3 }), e actual = _.defaults({ 'a': 1, 'b': 2 }, { 'b': 3 }, { 'c': 3 });
xpected);
assert.deepEqual(_.defaults({ 'a': 1, 'b': 2 }, { 'b': 3, 'c': 3 }, { 'c': assert.deepEqual(actual, expected);
2 }), expected);
actual = _.defaults({ 'a': 1, 'b': 2 }, { 'b': 3, 'c': 3 }, { 'c': 2 });
assert.deepEqual(actual, expected);
}); });
QUnit.test('should not overwrite `null` values', function(assert) { QUnit.test('should not overwrite `null` values', function(assert) {
assert.expect(1); assert.expect(1);
var actual = _.defaults({ 'a': null }, { 'a': 1 }); var actual = _.defaults({ 'a': null }, { 'a': 1 });
assert.strictEqual(actual.a, null); assert.strictEqual(actual.a, null);
}); });
QUnit.test('should overwrite `undefined` values', function(assert) { QUnit.test('should overwrite `undefined` values', function(assert) {
assert.expect(1); assert.expect(1);
var actual = _.defaults({ 'a': undefined }, { 'a': 1 }); var actual = _.defaults({ 'a': undefined }, { 'a': 1 });
assert.strictEqual(actual.a, 1); assert.strictEqual(actual.a, 1);
}); });
QUnit.test('should assign `undefined` values', function(assert) {
assert.expect(1);
var source = { 'a': undefined, 'b': 1 },
actual = _.defaults({}, source);
assert.deepEqual(actual, { 'a': undefined, 'b': 1 });
});
QUnit.test('should assign properties that shadow those on `Object.prototype` ', function(assert) { QUnit.test('should assign properties that shadow those on `Object.prototype` ', function(assert) {
assert.expect(2); assert.expect(2);
var object = { var object = {
'constructor': objectProto.constructor, 'constructor': objectProto.constructor,
'hasOwnProperty': objectProto.hasOwnProperty, 'hasOwnProperty': objectProto.hasOwnProperty,
'isPrototypeOf': objectProto.isPrototypeOf, 'isPrototypeOf': objectProto.isPrototypeOf,
'propertyIsEnumerable': objectProto.propertyIsEnumerable, 'propertyIsEnumerable': objectProto.propertyIsEnumerable,
'toLocaleString': objectProto.toLocaleString, 'toLocaleString': objectProto.toLocaleString,
'toString': objectProto.toString, 'toString': objectProto.toString,
skipping to change at line 3958 skipping to change at line 4588
var source = { var source = {
'constructor': 1, 'constructor': 1,
'hasOwnProperty': 2, 'hasOwnProperty': 2,
'isPrototypeOf': 3, 'isPrototypeOf': 3,
'propertyIsEnumerable': 4, 'propertyIsEnumerable': 4,
'toLocaleString': 5, 'toLocaleString': 5,
'toString': 6, 'toString': 6,
'valueOf': 7 'valueOf': 7
}; };
assert.deepEqual(_.defaults({}, source), source); var expected = lodashStable.clone(source);
assert.deepEqual(_.defaults({}, object, source), object); assert.deepEqual(_.defaults({}, source), expected);
expected = lodashStable.clone(object);
assert.deepEqual(_.defaults({}, object, source), expected);
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.defaultsDeep'); QUnit.module('lodash.defaultsDeep');
(function() { (function() {
QUnit.test('should deep assign source properties if missing on `object`', fu nction(assert) { QUnit.test('should deep assign source properties if missing on `object`', fu nction(assert) {
assert.expect(1); assert.expect(1);
var object = { 'a': { 'b': 2 }, 'd': 4 }, var object = { 'a': { 'b': 2 }, 'd': 4 },
source = { 'a': { 'b': 1, 'c': 3 }, 'e': 5 }, source = { 'a': { 'b': 3, 'c': 3 }, 'e': 5 },
expected = { 'a': { 'b': 2, 'c': 3 }, 'd': 4, 'e': 5 }; expected = { 'a': { 'b': 2, 'c': 3 }, 'd': 4, 'e': 5 };
assert.deepEqual(_.defaultsDeep(object, source), expected); assert.deepEqual(_.defaultsDeep(object, source), expected);
}); });
QUnit.test('should accept multiple sources', function(assert) { QUnit.test('should accept multiple sources', function(assert) {
assert.expect(2); assert.expect(2);
var source1 = { 'a': { 'b': 3 } }, var source1 = { 'a': { 'b': 3 } },
source2 = { 'a': { 'c': 3 } }, source2 = { 'a': { 'c': 3 } },
skipping to change at line 4001 skipping to change at line 4634
QUnit.test('should not overwrite `null` values', function(assert) { QUnit.test('should not overwrite `null` values', function(assert) {
assert.expect(1); assert.expect(1);
var object = { 'a': { 'b': null } }, var object = { 'a': { 'b': null } },
source = { 'a': { 'b': 2 } }, source = { 'a': { 'b': 2 } },
actual = _.defaultsDeep(object, source); actual = _.defaultsDeep(object, source);
assert.strictEqual(actual.a.b, null); assert.strictEqual(actual.a.b, null);
}); });
QUnit.test('should not overwrite regexp values', function(assert) {
assert.expect(1);
var object = { 'a': { 'b': /x/ } },
source = { 'a': { 'b': /y/ } },
actual = _.defaultsDeep(object, source);
assert.deepEqual(actual.a.b, /x/);
});
QUnit.test('should not convert function properties to objects', function(ass
ert) {
assert.expect(2);
var actual = _.defaultsDeep({}, { 'a': noop });
assert.strictEqual(actual.a, noop);
actual = _.defaultsDeep({}, { 'a': { 'b': noop } });
assert.strictEqual(actual.a.b, noop);
});
QUnit.test('should overwrite `undefined` values', function(assert) { QUnit.test('should overwrite `undefined` values', function(assert) {
assert.expect(1); assert.expect(1);
var object = { 'a': { 'b': undefined } }, var object = { 'a': { 'b': undefined } },
source = { 'a': { 'b': 2 } }, source = { 'a': { 'b': 2 } },
actual = _.defaultsDeep(object, source); actual = _.defaultsDeep(object, source);
assert.strictEqual(actual.a.b, 2); assert.strictEqual(actual.a.b, 2);
}); });
QUnit.test('should merge sources containing circular references', function(a ssert) { QUnit.test('should assign `undefined` values', function(assert) {
assert.expect(1); assert.expect(1);
var source = { 'a': undefined, 'b': { 'c': undefined, 'd': 1 } },
expected = lodashStable.cloneDeep(source),
actual = _.defaultsDeep({}, source);
assert.deepEqual(actual, expected);
});
QUnit.test('should merge sources containing circular references', function(a
ssert) {
assert.expect(2);
var object = { var object = {
'foo': { 'b': { 'c': { 'd': {} } } }, 'foo': { 'b': { 'c': { 'd': {} } } },
'bar': { 'a': 2 } 'bar': { 'a': 2 }
}; };
var source = { var source = {
'foo': { 'b': { 'c': { 'd': {} } } }, 'foo': { 'b': { 'c': { 'd': {} } } },
'bar': {} 'bar': {}
}; };
object.foo.b.c.d = object; object.foo.b.c.d = object;
source.foo.b.c.d = source; source.foo.b.c.d = source;
source.bar.b = source.foo.b; source.bar.b = source.foo.b;
var actual = _.defaultsDeep(object, source); 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); assert.strictEqual(actual.bar.b, actual.foo.b);
assert.strictEqual(actual.foo.b.c.d, actual.foo.b.c.d.foo.b.c.d);
}); });
QUnit.test('should not modify sources', function(assert) { QUnit.test('should not modify sources', function(assert) {
assert.expect(3); assert.expect(3);
var source1 = { 'a': 1, 'b': { 'c': 2 } }, var source1 = { 'a': 1, 'b': { 'c': 2 } },
source2 = { 'b': { 'c': 3, 'd': 3 } }, source2 = { 'b': { 'c': 3, 'd': 3 } },
actual = _.defaultsDeep({}, source1, source2); actual = _.defaultsDeep({}, source1, source2);
assert.deepEqual(actual, { 'a': 1, 'b': { 'c': 2, 'd': 3 } }); assert.deepEqual(actual, { 'a': 1, 'b': { 'c': 2, 'd': 3 } });
assert.deepEqual(source1, { 'a': 1, 'b': { 'c': 2 } }); assert.deepEqual(source1, { 'a': 1, 'b': { 'c': 2 } });
assert.deepEqual(source2, { 'b': { 'c': 3, 'd': 3 } }); assert.deepEqual(source2, { 'b': { 'c': 3, 'd': 3 } });
}); });
QUnit.test('should not attempt a merge of a string into an array', function( assert) { QUnit.test('should not attempt a merge of a string into an array', function( assert) {
assert.expect(1); assert.expect(1);
var actual = _.defaultsDeep({ 'a': ['abc'] }, { 'a': 'abc' }); var actual = _.defaultsDeep({ 'a': ['abc'] }, { 'a': 'abc' });
assert.deepEqual(actual, { 'a': ['abc'] }); assert.deepEqual(actual.a, ['abc']);
});
QUnit.test('should not indirectly merge `Object` properties', function(asser
t) {
assert.expect(1);
_.defaultsDeep({}, { 'constructor': { 'a': 1 } });
var actual = 'a' in Object;
delete Object.a;
assert.notOk(actual);
});
}());
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.defaultTo');
(function() {
QUnit.test('should return a default value if `value` is `NaN` or nullish', f
unction(assert) {
assert.expect(1);
var expected = lodashStable.map(falsey, function(value) {
return (value == null || value !== value) ? 1 : value;
});
var actual = lodashStable.map(falsey, function(value) {
return _.defaultTo(value, 1);
});
assert.deepEqual(actual, expected);
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.defer'); QUnit.module('lodash.defer');
(function() { (function() {
QUnit.test('should defer `func` execution', function(assert) { QUnit.test('should defer `func` execution', function(assert) {
assert.expect(1); assert.expect(1);
skipping to change at line 4093 skipping to change at line 4789
assert.deepEqual(args, [1, 2]); assert.deepEqual(args, [1, 2]);
done(); done();
}, 32); }, 32);
}); });
QUnit.test('should be cancelable', function(assert) { QUnit.test('should be cancelable', function(assert) {
assert.expect(1); assert.expect(1);
var done = assert.async(); var done = assert.async();
var pass = true; var pass = true,
timerId = _.defer(function() { pass = false; });
var timerId = _.defer(function() {
pass = false;
});
clearTimeout(timerId); clearTimeout(timerId);
setTimeout(function() { setTimeout(function() {
assert.ok(pass); assert.ok(pass);
done(); done();
}, 32); }, 32);
}); });
}()); }());
skipping to change at line 4154 skipping to change at line 4847
done(); done();
}, 64); }, 64);
}); });
QUnit.test('should use a default `wait` of `0`', function(assert) { QUnit.test('should use a default `wait` of `0`', function(assert) {
assert.expect(2); assert.expect(2);
var done = assert.async(); var done = assert.async();
var pass = false; var pass = false;
_.delay(function() { pass = true; });
_.delay(function() {
pass = true;
});
assert.notOk(pass); assert.notOk(pass);
setTimeout(function() { setTimeout(function() {
assert.ok(pass); assert.ok(pass);
done(); done();
}, 0); }, 0);
}); });
QUnit.test('should be cancelable', function(assert) { QUnit.test('should be cancelable', function(assert) {
assert.expect(1); assert.expect(1);
var done = assert.async(); var done = assert.async();
var pass = true; var pass = true,
timerId = _.delay(function() { pass = false; }, 32);
var timerId = _.delay(function() {
pass = false;
}, 32);
clearTimeout(timerId); clearTimeout(timerId);
setTimeout(function() { setTimeout(function() {
assert.ok(pass); assert.ok(pass);
done(); done();
}, 64); }, 64);
}); });
QUnit.test('should work with mocked `setTimeout`', function(assert) {
assert.expect(1);
if (!isPhantom) {
var pass = false,
setTimeout = root.setTimeout;
setProperty(root, 'setTimeout', function(func) { func(); });
_.delay(function() { pass = true; }, 32);
setProperty(root, 'setTimeout', setTimeout);
assert.ok(pass);
}
else {
skipAssert(assert);
}
});
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('difference methods'); QUnit.module('difference methods');
lodashStable.each(['difference', 'differenceBy', 'differenceWith'], function(m ethodName) { lodashStable.each(['difference', 'differenceBy', 'differenceWith'], function(m ethodName) {
var args = (function() { return arguments; }(1, 2, 3)), var func = _[methodName];
func = _[methodName];
QUnit.test('`_.' + methodName + '` should return the difference of the given QUnit.test('`_.' + methodName + '` should return the difference of two array
arrays', function(assert) { s', function(assert) {
assert.expect(1);
var actual = func([2, 1], [2, 3]);
assert.deepEqual(actual, [1]);
});
QUnit.test('`_.' + methodName + '` should return the difference of multiple
arrays', function(assert) {
assert.expect(1);
var actual = func([2, 1, 2, 3], [3, 4], [3, 2]);
assert.deepEqual(actual, [1]);
});
QUnit.test('`_.' + methodName + '` should treat `-0` as `0`', function(asser
t) {
assert.expect(2); assert.expect(2);
var actual = func([1, 2, 3, 4, 5], [5, 2, 10]); var array = [-0, 0];
assert.deepEqual(actual, [1, 3, 4]);
actual = func([1, 2, 3, 4, 5], [5, 2, 10], [8, 4]); var actual = lodashStable.map(array, function(value) {
assert.deepEqual(actual, [1, 3]); return func(array, [value]);
});
assert.deepEqual(actual, [[], []]);
actual = lodashStable.map(func([-0, 1], [1]), lodashStable.toString);
assert.deepEqual(actual, ['0']);
}); });
QUnit.test('`_.' + methodName + '` should match `NaN`', function(assert) { QUnit.test('`_.' + methodName + '` should match `NaN`', function(assert) {
assert.expect(1); assert.expect(1);
assert.deepEqual(func([1, NaN, 3], [NaN, 5, NaN]), [1, 3]); assert.deepEqual(func([1, NaN, 3], [NaN, 5, NaN]), [1, 3]);
}); });
QUnit.test('`_.' + methodName + '` should work with large arrays', function( assert) { QUnit.test('`_.' + methodName + '` should work with large arrays', function( assert) {
assert.expect(1); assert.expect(1);
skipping to change at line 4226 skipping to change at line 4949
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);
assert.deepEqual(func(array1, array2), [LARGE_ARRAY_SIZE]); assert.deepEqual(func(array1, array2), [LARGE_ARRAY_SIZE]);
}); });
QUnit.test('`_.' + methodName + '` should work with large arrays of objects' QUnit.test('`_.' + methodName + '` should work with large arrays of `-0` as
, function(assert) { `0`', function(assert) {
assert.expect(1); assert.expect(2);
var object1 = {}, var array = [-0, 0];
object2 = {},
largeArray = lodashStable.times(LARGE_ARRAY_SIZE, lodashStable.constan
t(object1));
assert.deepEqual(func([object1, object2], largeArray), [object2]); var actual = lodashStable.map(array, function(value) {
var largeArray = lodashStable.times(LARGE_ARRAY_SIZE, lodashStable.const
ant(value));
return func(array, largeArray);
});
assert.deepEqual(actual, [[], []]);
var largeArray = lodashStable.times(LARGE_ARRAY_SIZE, stubOne);
actual = lodashStable.map(func([-0, 1], largeArray), lodashStable.toString
);
assert.deepEqual(actual, ['0']);
}); });
QUnit.test('`_.' + methodName + '` should work with large arrays of `NaN`', function(assert) { QUnit.test('`_.' + methodName + '` should work with large arrays of `NaN`', function(assert) {
assert.expect(1); assert.expect(1);
var largeArray = lodashStable.times(LARGE_ARRAY_SIZE, alwaysNaN); var largeArray = lodashStable.times(LARGE_ARRAY_SIZE, stubNaN);
assert.deepEqual(func([1, NaN, 3], largeArray), [1, 3]); assert.deepEqual(func([1, NaN, 3], largeArray), [1, 3]);
}); });
QUnit.test('`_.' + methodName + '` should work with large arrays of objects'
, function(assert) {
assert.expect(1);
var object1 = {},
object2 = {},
largeArray = lodashStable.times(LARGE_ARRAY_SIZE, lodashStable.constan
t(object1));
assert.deepEqual(func([object1, object2], largeArray), [object2]);
});
QUnit.test('`_.' + methodName + '` should ignore values that are not array-l ike', function(assert) { QUnit.test('`_.' + methodName + '` should ignore values that are not array-l ike', function(assert) {
assert.expect(3); assert.expect(3);
var array = [1, null, 3]; var array = [1, null, 3];
assert.deepEqual(func(args, 3, { '0': 1 }), [1, 2, 3]); assert.deepEqual(func(args, 3, { '0': 1 }), [1, 2, 3]);
assert.deepEqual(func(null, array, 1), []); assert.deepEqual(func(null, array, 1), []);
assert.deepEqual(func(array, args, null), [null]); assert.deepEqual(func(array, args, null), [null]);
}); });
}); });
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.differenceBy'); QUnit.module('lodash.differenceBy');
(function() { (function() {
QUnit.test('should accept an `iteratee` argument', function(assert) { QUnit.test('should accept an `iteratee`', function(assert) {
assert.expect(2); assert.expect(2);
var actual = _.differenceBy([3.1, 2.2, 1.3], [4.4, 2.5], Math.floor); var actual = _.differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor);
assert.deepEqual(actual, [3.1, 1.3]); assert.deepEqual(actual, [1.2]);
actual = _.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x'); actual = _.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x');
assert.deepEqual(actual, [{ 'x': 2 }]); assert.deepEqual(actual, [{ 'x': 2 }]);
}); });
QUnit.test('should provide the correct `iteratee` arguments', function(asser t) { QUnit.test('should provide correct `iteratee` arguments', function(assert) {
assert.expect(1); assert.expect(1);
var args; var args;
_.differenceBy([3.1, 2.2, 1.3], [4.4, 2.5], function() { _.differenceBy([2.1, 1.2], [2.3, 3.4], function() {
args || (args = slice.call(arguments)); args || (args = slice.call(arguments));
}); });
assert.deepEqual(args, [4.4]); assert.deepEqual(args, [2.3]);
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.differenceWith'); QUnit.module('lodash.differenceWith');
(function() { (function() {
var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; QUnit.test('should work with a `comparator`', function(assert) {
assert.expect(1);
var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }],
actual = _.differenceWith(objects, [{ 'x': 1, 'y': 2 }], lodashStable.
isEqual);
assert.deepEqual(actual, [objects[1]]);
});
QUnit.test('should work with a `comparator` argument', function(assert) { QUnit.test('should preserve the sign of `0`', function(assert) {
assert.expect(1); assert.expect(1);
var actual = _.differenceWith(objects, [{ 'x': 1, 'y': 2 }], lodashStable. var array = [-0, 1],
isEqual); largeArray = lodashStable.times(LARGE_ARRAY_SIZE, stubOne),
assert.deepEqual(actual, [{ 'x': 2, 'y': 1 }]); others = [[1], largeArray],
expected = lodashStable.map(others, lodashStable.constant(['-0']));
var actual = lodashStable.map(others, function(other) {
return lodashStable.map(_.differenceWith(array, other, lodashStable.eq),
lodashStable.toString);
});
assert.deepEqual(actual, expected);
});
}());
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.divide');
(function() {
QUnit.test('should divide two numbers', function(assert) {
assert.expect(3);
assert.strictEqual(_.divide(6, 4), 1.5);
assert.strictEqual(_.divide(-6, 4), -1.5);
assert.strictEqual(_.divide(-6, -4), 1.5);
});
QUnit.test('should coerce arguments to numbers', function(assert) {
assert.expect(2);
assert.strictEqual(_.divide('6', '4'), 1.5);
assert.deepEqual(_.divide('x', 'y'), NaN);
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.drop'); QUnit.module('lodash.drop');
(function() { (function() {
var array = [1, 2, 3]; var array = [1, 2, 3];
skipping to change at line 4331 skipping to change at line 5108
}); });
QUnit.test('should return all elements when `n` < `1`', function(assert) { QUnit.test('should return all elements when `n` < `1`', function(assert) {
assert.expect(3); assert.expect(3);
lodashStable.each([0, -1, -Infinity], function(n) { lodashStable.each([0, -1, -Infinity], function(n) {
assert.deepEqual(_.drop(array, n), array); assert.deepEqual(_.drop(array, n), array);
}); });
}); });
QUnit.test('should return an empty array when `n` >= `array.length`', functi on(assert) { QUnit.test('should return an empty array when `n` >= `length`', function(ass ert) {
assert.expect(4); assert.expect(4);
lodashStable.each([3, 4, Math.pow(2, 32), Infinity], function(n) { lodashStable.each([3, 4, Math.pow(2, 32), Infinity], function(n) {
assert.deepEqual(_.drop(array, n), []); assert.deepEqual(_.drop(array, n), []);
}); });
}); });
QUnit.test('should coerce `n` to an integer', function(assert) { QUnit.test('should coerce `n` to an integer', function(assert) {
assert.expect(1); assert.expect(1);
skipping to change at line 4379 skipping to change at line 5156
actual = _(array).drop(2).dropRight().drop().dropRight(2).value(); actual = _(array).drop(2).dropRight().drop().dropRight(2).value();
assert.deepEqual(actual, _.dropRight(_.drop(_.dropRight(_.drop(array, 2) )), 2)); assert.deepEqual(actual, _.dropRight(_.drop(_.dropRight(_.drop(array, 2) )), 2));
values = []; values = [];
actual = _(array).drop().filter(predicate).drop(2).dropRight().drop().dr opRight(2).value(); actual = _(array).drop().filter(predicate).drop(2).dropRight().drop().dr opRight(2).value();
assert.deepEqual(values, array.slice(1)); assert.deepEqual(values, array.slice(1));
assert.deepEqual(actual, _.dropRight(_.drop(_.dropRight(_.drop(_.filter( _.drop(array), predicate), 2))), 2)); assert.deepEqual(actual, _.dropRight(_.drop(_.dropRight(_.drop(_.filter( _.drop(array), predicate), 2))), 2));
} }
else { else {
skipTest(assert, 6); skipAssert(assert, 6);
} }
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.dropRight'); QUnit.module('lodash.dropRight');
(function() { (function() {
var array = [1, 2, 3]; var array = [1, 2, 3];
skipping to change at line 4419 skipping to change at line 5196
}); });
QUnit.test('should return all elements when `n` < `1`', function(assert) { QUnit.test('should return all elements when `n` < `1`', function(assert) {
assert.expect(3); assert.expect(3);
lodashStable.each([0, -1, -Infinity], function(n) { lodashStable.each([0, -1, -Infinity], function(n) {
assert.deepEqual(_.dropRight(array, n), array); assert.deepEqual(_.dropRight(array, n), array);
}); });
}); });
QUnit.test('should return an empty array when `n` >= `array.length`', functi on(assert) { QUnit.test('should return an empty array when `n` >= `length`', function(ass ert) {
assert.expect(4); assert.expect(4);
lodashStable.each([3, 4, Math.pow(2, 32), Infinity], function(n) { lodashStable.each([3, 4, Math.pow(2, 32), Infinity], function(n) {
assert.deepEqual(_.dropRight(array, n), []); assert.deepEqual(_.dropRight(array, n), []);
}); });
}); });
QUnit.test('should coerce `n` to an integer', function(assert) { QUnit.test('should coerce `n` to an integer', function(assert) {
assert.expect(1); assert.expect(1);
skipping to change at line 4467 skipping to change at line 5244
actual = _(array).dropRight(2).drop().dropRight().drop(2).value(); actual = _(array).dropRight(2).drop().dropRight().drop(2).value();
assert.deepEqual(actual, _.drop(_.dropRight(_.drop(_.dropRight(array, 2) )), 2)); assert.deepEqual(actual, _.drop(_.dropRight(_.drop(_.dropRight(array, 2) )), 2));
values = []; values = [];
actual = _(array).dropRight().filter(predicate).dropRight(2).drop().drop Right().drop(2).value(); actual = _(array).dropRight().filter(predicate).dropRight(2).drop().drop Right().drop(2).value();
assert.deepEqual(values, array.slice(0, -1)); assert.deepEqual(values, array.slice(0, -1));
assert.deepEqual(actual, _.drop(_.dropRight(_.drop(_.dropRight(_.filter( _.dropRight(array), predicate), 2))), 2)); assert.deepEqual(actual, _.drop(_.dropRight(_.drop(_.dropRight(_.filter( _.dropRight(array), predicate), 2))), 2));
} }
else { else {
skipTest(assert, 6); skipAssert(assert, 6);
} }
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.dropRightWhile'); QUnit.module('lodash.dropRightWhile');
(function() { (function() {
var array = [1, 2, 3, 4]; 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 }
]; ];
QUnit.test('should drop elements while `predicate` returns truthy', function (assert) { QUnit.test('should drop elements while `predicate` returns truthy', function (assert) {
assert.expect(1); assert.expect(1);
var actual = _.dropRightWhile(array, function(num) { var actual = _.dropRightWhile(array, function(n) {
return num > 2; return n > 2;
}); });
assert.deepEqual(actual, [1, 2]); assert.deepEqual(actual, [1, 2]);
}); });
QUnit.test('should provide the correct `predicate` arguments', function(asse rt) { QUnit.test('should provide correct `predicate` arguments', function(assert) {
assert.expect(1); assert.expect(1);
var args; var args;
_.dropRightWhile(array, function() { _.dropRightWhile(array, function() {
args = slice.call(arguments); args = slice.call(arguments);
}); });
assert.deepEqual(args, [4, 3, array]); assert.deepEqual(args, [4, 3, array]);
}); });
QUnit.test('should work with a "_.matches" style `predicate`', function(asse rt) { QUnit.test('should work with `_.matches` shorthands', function(assert) {
assert.expect(1); assert.expect(1);
assert.deepEqual(_.dropRightWhile(objects, { 'b': 2 }), objects.slice(0, 2 )); assert.deepEqual(_.dropRightWhile(objects, { 'b': 2 }), objects.slice(0, 2 ));
}); });
QUnit.test('should work with a "_.matchesProperty" style `predicate`', funct ion(assert) { QUnit.test('should work with `_.matchesProperty` shorthands', function(asser t) {
assert.expect(1); assert.expect(1);
assert.deepEqual(_.dropRightWhile(objects, ['b', 2]), objects.slice(0, 2)) ; assert.deepEqual(_.dropRightWhile(objects, ['b', 2]), objects.slice(0, 2)) ;
}); });
QUnit.test('should work with a "_.property" style `predicate`', function(ass ert) { QUnit.test('should work with `_.property` shorthands', function(assert) {
assert.expect(1); assert.expect(1);
assert.deepEqual(_.dropRightWhile(objects, 'b'), objects.slice(0, 1)); assert.deepEqual(_.dropRightWhile(objects, 'b'), objects.slice(0, 1));
}); });
QUnit.test('should return a wrapped value when chaining', function(assert) { QUnit.test('should return a wrapped value when chaining', function(assert) {
assert.expect(2); assert.expect(2);
if (!isNpm) { if (!isNpm) {
var wrapped = _(array).dropRightWhile(function(num) { var wrapped = _(array).dropRightWhile(function(n) {
return num > 2; return n > 2;
}); });
assert.ok(wrapped instanceof _); assert.ok(wrapped instanceof _);
assert.deepEqual(wrapped.value(), [1, 2]); assert.deepEqual(wrapped.value(), [1, 2]);
} }
else { else {
skipTest(assert, 2); skipAssert(assert, 2);
} }
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.dropWhile'); QUnit.module('lodash.dropWhile');
(function() { (function() {
var array = [1, 2, 3, 4]; 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 }
]; ];
QUnit.test('should drop elements while `predicate` returns truthy', function (assert) { QUnit.test('should drop elements while `predicate` returns truthy', function (assert) {
assert.expect(1); assert.expect(1);
var actual = _.dropWhile(array, function(num) { var actual = _.dropWhile(array, function(n) {
return num < 3; return n < 3;
}); });
assert.deepEqual(actual, [3, 4]); assert.deepEqual(actual, [3, 4]);
}); });
QUnit.test('should provide the correct `predicate` arguments', function(asse rt) { QUnit.test('should provide correct `predicate` arguments', function(assert) {
assert.expect(1); assert.expect(1);
var args; var args;
_.dropWhile(array, function() { _.dropWhile(array, function() {
args = slice.call(arguments); args = slice.call(arguments);
}); });
assert.deepEqual(args, [1, 0, array]); assert.deepEqual(args, [1, 0, array]);
}); });
QUnit.test('should work with a "_.matches" style `predicate`', function(asse rt) { QUnit.test('should work with `_.matches` shorthands', function(assert) {
assert.expect(1); assert.expect(1);
assert.deepEqual(_.dropWhile(objects, { 'b': 2 }), objects.slice(1)); assert.deepEqual(_.dropWhile(objects, { 'b': 2 }), objects.slice(1));
}); });
QUnit.test('should work with a "_.matchesProperty" style `predicate`', funct ion(assert) { QUnit.test('should work with `_.matchesProperty` shorthands', function(asser t) {
assert.expect(1); assert.expect(1);
assert.deepEqual(_.dropWhile(objects, ['b', 2]), objects.slice(1)); assert.deepEqual(_.dropWhile(objects, ['b', 2]), objects.slice(1));
}); });
QUnit.test('should work with a "_.property" style `predicate`', function(ass ert) { QUnit.test('should work with `_.property` shorthands', function(assert) {
assert.expect(1); assert.expect(1);
assert.deepEqual(_.dropWhile(objects, 'b'), objects.slice(2)); assert.deepEqual(_.dropWhile(objects, 'b'), objects.slice(2));
}); });
QUnit.test('should work in a lazy sequence', function(assert) { QUnit.test('should work in a lazy sequence', function(assert) {
assert.expect(3); assert.expect(3);
if (!isNpm) { if (!isNpm) {
var array = lodashStable.range(1, LARGE_ARRAY_SIZE + 3), var array = lodashStable.range(1, LARGE_ARRAY_SIZE + 3),
predicate = function(num) { return num < 3; }, predicate = function(n) { return n < 3; },
expected = _.dropWhile(array, predicate), expected = _.dropWhile(array, predicate),
wrapped = _(array).dropWhile(predicate); wrapped = _(array).dropWhile(predicate);
assert.deepEqual(wrapped.value(), expected); assert.deepEqual(wrapped.value(), expected);
assert.deepEqual(wrapped.reverse().value(), expected.slice().reverse()); assert.deepEqual(wrapped.reverse().value(), expected.slice().reverse());
assert.strictEqual(wrapped.last(), _.last(expected)); assert.strictEqual(wrapped.last(), _.last(expected));
} }
else { else {
skipTest(assert, 3); skipAssert(assert, 3);
} }
}); });
QUnit.test('should work in a lazy sequence with `drop`', function(assert) { QUnit.test('should work in a lazy sequence with `drop`', function(assert) {
assert.expect(1); assert.expect(1);
if (!isNpm) { if (!isNpm) {
var array = lodashStable.range(1, LARGE_ARRAY_SIZE + 3); var array = lodashStable.range(1, LARGE_ARRAY_SIZE + 3);
var actual = _(array) var actual = _(array)
.dropWhile(function(num) { return num == 1; }) .dropWhile(function(n) { return n == 1; })
.drop() .drop()
.dropWhile(function(num) { return num == 3; }) .dropWhile(function(n) { return n == 3; })
.value(); .value();
assert.deepEqual(actual, array.slice(3)); assert.deepEqual(actual, array.slice(3));
} }
else { else {
skipTest(assert); skipAssert(assert);
} }
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.endsWith'); QUnit.module('lodash.endsWith');
(function() { (function() {
var string = 'abc'; var string = 'abc';
skipping to change at line 4652 skipping to change at line 5429
assert.strictEqual(_.endsWith(string, 'c'), true); assert.strictEqual(_.endsWith(string, 'c'), true);
}); });
QUnit.test('should return `false` if a string does not end with `target`', f unction(assert) { QUnit.test('should return `false` if a string does not end with `target`', f unction(assert) {
assert.expect(1); assert.expect(1);
assert.strictEqual(_.endsWith(string, 'b'), false); assert.strictEqual(_.endsWith(string, 'b'), false);
}); });
QUnit.test('should work with a `position` argument', function(assert) { QUnit.test('should work with a `position`', function(assert) {
assert.expect(1); assert.expect(1);
assert.strictEqual(_.endsWith(string, 'b', 2), true); assert.strictEqual(_.endsWith(string, 'b', 2), true);
}); });
QUnit.test('should work with `position` >= `string.length`', function(assert ) { QUnit.test('should work with `position` >= `length`', function(assert) {
assert.expect(4); assert.expect(4);
lodashStable.each([3, 5, MAX_SAFE_INTEGER, Infinity], function(position) { lodashStable.each([3, 5, MAX_SAFE_INTEGER, Infinity], function(position) {
assert.strictEqual(_.endsWith(string, 'c', position), true); assert.strictEqual(_.endsWith(string, 'c', position), true);
}); });
}); });
QUnit.test('should treat falsey `position` values, except `undefined`, as `0 `', function(assert) { QUnit.test('should treat falsey `position` values, except `undefined`, as `0 `', function(assert) {
assert.expect(1); assert.expect(1);
var expected = lodashStable.map(falsey, alwaysTrue); var expected = lodashStable.map(falsey, stubTrue);
var actual = lodashStable.map(falsey, function(position) { var actual = lodashStable.map(falsey, function(position) {
return _.endsWith(string, position === undefined ? 'c' : '', position); return _.endsWith(string, position === undefined ? 'c' : '', position);
}); });
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
}); });
QUnit.test('should treat a negative `position` as `0`', function(assert) { QUnit.test('should treat a negative `position` as `0`', function(assert) {
assert.expect(6); assert.expect(6);
lodashStable.each([-1, -3, -Infinity], function(position) { lodashStable.each([-1, -3, -Infinity], function(position) {
assert.ok(lodashStable.every(string, function(chr) { assert.ok(lodashStable.every(string, function(chr) {
return _.endsWith(string, chr, position) === false; return !_.endsWith(string, chr, position);
})); }));
assert.strictEqual(_.endsWith(string, '', position), true); assert.strictEqual(_.endsWith(string, '', position), true);
}); });
}); });
QUnit.test('should coerce `position` to an integer', function(assert) { QUnit.test('should coerce `position` to an integer', function(assert) {
assert.expect(1); assert.expect(1);
assert.strictEqual(_.endsWith(string, 'ab', 2.2), true); 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);
}));
});
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.eq'); QUnit.module('lodash.eq');
(function() { (function() {
QUnit.test('should perform a `SameValueZero` comparison of two values', func tion(assert) { QUnit.test('should perform a `SameValueZero` comparison of two values', func tion(assert) {
assert.expect(11); assert.expect(11);
skipping to change at line 4734 skipping to change at line 5503
assert.strictEqual(_.eq(object, object), true); assert.strictEqual(_.eq(object, object), true);
assert.strictEqual(_.eq(object, { 'a': 1 }), false); 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;/',
unescaped = '&<>"\'`\/'; unescaped = '&<>"\'/';
escaped += escaped; escaped += escaped;
unescaped += unescaped; unescaped += unescaped;
QUnit.test('should escape values', function(assert) { QUnit.test('should escape values', function(assert) {
assert.expect(1); assert.expect(1);
assert.strictEqual(_.escape(unescaped), escaped); assert.strictEqual(_.escape(unescaped), escaped);
}); });
QUnit.test('should not escape the "/" character', function(assert) {
assert.expect(1);
assert.strictEqual(_.escape('/'), '/');
});
QUnit.test('should handle strings with nothing to escape', function(assert) { QUnit.test('should handle strings with nothing to escape', function(assert) {
assert.expect(1); assert.expect(1);
assert.strictEqual(_.escape('abc'), 'abc'); assert.strictEqual(_.escape('abc'), 'abc');
}); });
QUnit.test('should escape the same characters unescaped by `_.unescape`', fu nction(assert) { QUnit.test('should escape the same characters unescaped by `_.unescape`', fu nction(assert) {
assert.expect(1); assert.expect(1);
assert.strictEqual(_.escape(_.unescape(escaped)), escaped); assert.strictEqual(_.escape(_.unescape(escaped)), escaped);
}); });
lodashStable.each(['`', '/'], function(chr) {
QUnit.test('should not escape the "' + chr + '" character', function(asser
t) {
assert.expect(1);
assert.strictEqual(_.escape(chr), chr);
});
});
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.escapeRegExp'); QUnit.module('lodash.escapeRegExp');
(function() { (function() {
var escaped = '\\^\\$\\.\\*\\+\\?\\(\\)\\[\\]\\{\\}\\|\\\\', var escaped = '\\^\\$\\.\\*\\+\\?\\(\\)\\[\\]\\{\\}\\|\\\\',
unescaped = '^$.*+?()[]{}|\\'; unescaped = '^$.*+?()[]{}|\\';
QUnit.test('should escape values', function(assert) { QUnit.test('should escape values', function(assert) {
assert.expect(1); assert.expect(1);
assert.strictEqual(_.escapeRegExp(unescaped + unescaped), escaped + escape d); assert.strictEqual(_.escapeRegExp(unescaped + unescaped), escaped + escape d);
}); });
QUnit.test('should handle strings with nothing to escape', function(assert) { QUnit.test('should handle strings with nothing to escape', function(assert) {
assert.expect(1); assert.expect(1);
assert.strictEqual(_.escapeRegExp('ghi'), 'ghi'); assert.strictEqual(_.escapeRegExp('abc'), 'abc');
}); });
QUnit.test('should return an empty string for empty values', function(assert ) { QUnit.test('should return an empty string for empty values', function(assert ) {
assert.expect(1); assert.expect(1);
var values = [, null, undefined, ''], var values = [, null, undefined, ''],
expected = lodashStable.map(values, alwaysEmptyString); expected = lodashStable.map(values, stubString);
var actual = lodashStable.map(values, function(value, index) { var actual = lodashStable.map(values, function(value, index) {
return index ? _.escapeRegExp(value) : _.escapeRegExp(); return index ? _.escapeRegExp(value) : _.escapeRegExp();
}); });
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
skipping to change at line 4813 skipping to change at line 5584
(function() { (function() {
QUnit.test('should return `true` if `predicate` returns truthy for all eleme nts', function(assert) { QUnit.test('should return `true` if `predicate` returns truthy for all eleme nts', function(assert) {
assert.expect(1); assert.expect(1);
assert.strictEqual(lodashStable.every([true, 1, 'a'], identity), true); assert.strictEqual(lodashStable.every([true, 1, 'a'], identity), true);
}); });
QUnit.test('should return `true` for empty collections', function(assert) { QUnit.test('should return `true` for empty collections', function(assert) {
assert.expect(1); assert.expect(1);
var expected = lodashStable.map(empties, alwaysTrue); var expected = lodashStable.map(empties, stubTrue);
var actual = lodashStable.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) {}
}); });
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
}); });
skipping to change at line 4847 skipping to change at line 5618
QUnit.test('should work with collections of `undefined` values (test in IE < 9)', function(assert) { QUnit.test('should work with collections of `undefined` values (test in IE < 9)', function(assert) {
assert.expect(1); assert.expect(1);
assert.strictEqual(_.every([undefined, undefined, undefined], identity), f alse); assert.strictEqual(_.every([undefined, undefined, undefined], identity), f alse);
}); });
QUnit.test('should use `_.identity` when `predicate` is nullish', function(a ssert) { QUnit.test('should use `_.identity` when `predicate` is nullish', function(a ssert) {
assert.expect(2); assert.expect(2);
var values = [, null, undefined], var values = [, null, undefined],
expected = lodashStable.map(values, alwaysFalse); expected = lodashStable.map(values, stubFalse);
var actual = lodashStable.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);
}); });
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
expected = lodashStable.map(values, alwaysTrue); expected = lodashStable.map(values, stubTrue);
actual = lodashStable.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);
}); });
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
}); });
QUnit.test('should work with a "_.property" style `predicate`', function(ass ert) { QUnit.test('should work with `_.property` shorthands', function(assert) {
assert.expect(2); assert.expect(2);
var objects = [{ 'a': 0, 'b': 1 }, { 'a': 1, 'b': 2 }]; var objects = [{ 'a': 0, 'b': 1 }, { 'a': 1, 'b': 2 }];
assert.strictEqual(_.every(objects, 'a'), false); assert.strictEqual(_.every(objects, 'a'), false);
assert.strictEqual(_.every(objects, 'b'), true); assert.strictEqual(_.every(objects, 'b'), true);
}); });
QUnit.test('should work with a "_.matches" style `predicate`', function(asse rt) { QUnit.test('should work with `_.matches` shorthands', function(assert) {
assert.expect(2); assert.expect(2);
var objects = [{ 'a': 0, 'b': 0 }, { 'a': 0, 'b': 1 }]; var objects = [{ 'a': 0, 'b': 0 }, { 'a': 0, 'b': 1 }];
assert.strictEqual(_.every(objects, { 'a': 0 }), true); assert.strictEqual(_.every(objects, { 'a': 0 }), true);
assert.strictEqual(_.every(objects, { 'b': 1 }), false); assert.strictEqual(_.every(objects, { 'b': 1 }), false);
}); });
QUnit.test('should work as an iteratee for methods like `_.map`', function(a ssert) { QUnit.test('should work as an iteratee for methods like `_.map`', function(a ssert) {
assert.expect(1); assert.expect(1);
var actual = lodashStable.map([[1]], _.every); var actual = lodashStable.map([[1]], _.every);
assert.deepEqual(actual, [true]); assert.deepEqual(actual, [true]);
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('strict mode checks'); QUnit.module('strict mode checks');
lodashStable.each(['assign', 'assignIn', 'bindAll', 'defaults'], function(meth odName) { lodashStable.each(['assign', 'assignIn', 'bindAll', 'defaults', 'defaultsDeep' , 'merge'], function(methodName) {
var func = _[methodName], var func = _[methodName],
isBindAll = methodName == 'bindAll'; isBindAll = methodName == 'bindAll';
QUnit.test('`_.' + methodName + '` should ' + (isStrict ? '' : 'not ') + 'th row strict mode errors', function(assert) { QUnit.test('`_.' + methodName + '` should ' + (isStrict ? '' : 'not ') + 'th row strict mode errors', function(assert) {
assert.expect(1); assert.expect(1);
if (freeze) { var object = freeze({ 'a': undefined, 'b': function() {} }),
var object = freeze({ 'a': undefined, 'b': function() {} }), pass = !isStrict;
pass = !isStrict;
try { try {
func(object, isBindAll ? 'b' : { 'a': 1 }); func(object, isBindAll ? 'b' : { 'a': 1 });
} catch (e) { } catch (e) {
pass = !pass; pass = !pass;
}
assert.ok(pass);
}
else {
skipTest(assert);
} }
assert.ok(pass);
}); });
}); });
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.fill'); QUnit.module('lodash.fill');
(function() { (function() {
QUnit.test('should use a default `start` of `0` and a default `end` of `arra y.length`', function(assert) { QUnit.test('should use a default `start` of `0` and a default `end` of `leng th`', function(assert) {
assert.expect(1); assert.expect(1);
var array = [1, 2, 3]; var array = [1, 2, 3];
assert.deepEqual(_.fill(array, 'a'), ['a', 'a', 'a']); assert.deepEqual(_.fill(array, 'a'), ['a', 'a', 'a']);
}); });
QUnit.test('should use `undefined` for `value` if not provided', function(as sert) { QUnit.test('should use `undefined` for `value` if not given', function(asser t) {
assert.expect(2); assert.expect(2);
var array = [1, 2, 3], var array = [1, 2, 3],
actual = _.fill(array); actual = _.fill(array);
assert.deepEqual(actual, Array(3)); assert.deepEqual(actual, Array(3));
assert.ok(lodashStable.every(actual, function(value, index) { assert.ok(lodashStable.every(actual, function(value, index) {
return index in actual; return index in actual;
})); }));
}); });
QUnit.test('should work with a positive `start`', function(assert) { QUnit.test('should work with a positive `start`', function(assert) {
assert.expect(1); assert.expect(1);
var array = [1, 2, 3]; var array = [1, 2, 3];
assert.deepEqual(_.fill(array, 'a', 1), [1, 'a', 'a']); assert.deepEqual(_.fill(array, 'a', 1), [1, 'a', 'a']);
}); });
QUnit.test('should work with a `start` >= `array.length`', function(assert) { QUnit.test('should work with a `start` >= `length`', function(assert) {
assert.expect(4); assert.expect(4);
lodashStable.each([3, 4, Math.pow(2, 32), Infinity], function(start) { lodashStable.each([3, 4, Math.pow(2, 32), Infinity], function(start) {
var array = [1, 2, 3]; var array = [1, 2, 3];
assert.deepEqual(_.fill(array, 'a', start), [1, 2, 3]); assert.deepEqual(_.fill(array, 'a', start), [1, 2, 3]);
}); });
}); });
QUnit.test('should treat falsey `start` values as `0`', function(assert) { QUnit.test('should treat falsey `start` values as `0`', function(assert) {
assert.expect(1); assert.expect(1);
skipping to change at line 4977 skipping to change at line 5743
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
}); });
QUnit.test('should work with a negative `start`', function(assert) { QUnit.test('should work with a negative `start`', function(assert) {
assert.expect(1); assert.expect(1);
var array = [1, 2, 3]; var array = [1, 2, 3];
assert.deepEqual(_.fill(array, 'a', -1), [1, 2, 'a']); assert.deepEqual(_.fill(array, 'a', -1), [1, 2, 'a']);
}); });
QUnit.test('should work with a negative `start` <= negative `array.length`', function(assert) { QUnit.test('should work with a negative `start` <= negative `length`', funct ion(assert) {
assert.expect(3); assert.expect(3);
lodashStable.each([-3, -4, -Infinity], function(start) { lodashStable.each([-3, -4, -Infinity], function(start) {
var array = [1, 2, 3]; var array = [1, 2, 3];
assert.deepEqual(_.fill(array, 'a', start), ['a', 'a', 'a']); assert.deepEqual(_.fill(array, 'a', start), ['a', 'a', 'a']);
}); });
}); });
QUnit.test('should work with `start` >= `end`', function(assert) { QUnit.test('should work with `start` >= `end`', function(assert) {
assert.expect(2); assert.expect(2);
skipping to change at line 5002 skipping to change at line 5768
}); });
}); });
QUnit.test('should work with a positive `end`', function(assert) { QUnit.test('should work with a positive `end`', function(assert) {
assert.expect(1); assert.expect(1);
var array = [1, 2, 3]; var array = [1, 2, 3];
assert.deepEqual(_.fill(array, 'a', 0, 1), ['a', 2, 3]); assert.deepEqual(_.fill(array, 'a', 0, 1), ['a', 2, 3]);
}); });
QUnit.test('should work with a `end` >= `array.length`', function(assert) { QUnit.test('should work with a `end` >= `length`', function(assert) {
assert.expect(4); assert.expect(4);
lodashStable.each([3, 4, Math.pow(2, 32), Infinity], function(end) { lodashStable.each([3, 4, Math.pow(2, 32), Infinity], function(end) {
var array = [1, 2, 3]; var array = [1, 2, 3];
assert.deepEqual(_.fill(array, 'a', 0, end), ['a', 'a', 'a']); assert.deepEqual(_.fill(array, 'a', 0, end), ['a', 'a', 'a']);
}); });
}); });
QUnit.test('should treat falsey `end` values, except `undefined`, as `0`', f unction(assert) { QUnit.test('should treat falsey `end` values, except `undefined`, as `0`', f unction(assert) {
assert.expect(1); assert.expect(1);
skipping to change at line 5033 skipping to change at line 5799
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
}); });
QUnit.test('should work with a negative `end`', function(assert) { QUnit.test('should work with a negative `end`', function(assert) {
assert.expect(1); assert.expect(1);
var array = [1, 2, 3]; var array = [1, 2, 3];
assert.deepEqual(_.fill(array, 'a', 0, -1), ['a', 'a', 3]); assert.deepEqual(_.fill(array, 'a', 0, -1), ['a', 'a', 3]);
}); });
QUnit.test('should work with a negative `end` <= negative `array.length`', f unction(assert) { QUnit.test('should work with a negative `end` <= negative `length`', functio n(assert) {
assert.expect(3); assert.expect(3);
lodashStable.each([-3, -4, -Infinity], function(end) { lodashStable.each([-3, -4, -Infinity], function(end) {
var array = [1, 2, 3]; var array = [1, 2, 3];
assert.deepEqual(_.fill(array, 'a', 0, end), [1, 2, 3]); assert.deepEqual(_.fill(array, 'a', 0, end), [1, 2, 3]);
}); });
}); });
QUnit.test('should coerce `start` and `end` to integers', function(assert) { QUnit.test('should coerce `start` and `end` to integers', function(assert) {
assert.expect(1); assert.expect(1);
skipping to change at line 5073 skipping to change at line 5839
QUnit.test('should return a wrapped value when chaining', function(assert) { QUnit.test('should return a wrapped value when chaining', function(assert) {
assert.expect(3); assert.expect(3);
if (!isNpm) { if (!isNpm) {
var array = [1, 2, 3], var array = [1, 2, 3],
wrapped = _(array).fill('a'), wrapped = _(array).fill('a'),
actual = wrapped.value(); actual = wrapped.value();
assert.ok(wrapped instanceof _); assert.ok(wrapped instanceof _);
assert.deepEqual(actual, ['a', 'a', 'a']);
assert.strictEqual(actual, array); assert.strictEqual(actual, array);
assert.deepEqual(actual, ['a', 'a', 'a']);
} }
else { else {
skipTest(assert, 3); skipAssert(assert, 3);
} }
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.filter'); QUnit.module('lodash.filter');
(function() { (function() {
var array = [1, 2, 3]; var array = [1, 2, 3];
QUnit.test('should return elements `predicate` returns truthy for', function (assert) { QUnit.test('should return elements `predicate` returns truthy for', function (assert) {
assert.expect(1); assert.expect(1);
assert.deepEqual(_.filter(array, isEven), [2]); assert.deepEqual(_.filter(array, isEven), [2]);
}); });
QUnit.test('should iterate over an object with numeric keys (test in Mobile
Safari 8)', function(assert) {
assert.expect(1);
// 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' };
lodashStable.times(1000, function(assert) {
_.filter([], alwaysTrue);
});
_.filter(object, function() {
counter++;
return true;
});
assert.strictEqual(counter, 3);
});
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
lodashStable.each(['find', 'findLast', 'findIndex', 'findLastIndex', 'findKey' , 'findLastKey'], function(methodName) { lodashStable.each(['find', 'findIndex', 'findKey', 'findLast', 'findLastIndex' , 'findLastKey'], function(methodName) {
QUnit.module('lodash.' + methodName); QUnit.module('lodash.' + methodName);
var func = _[methodName], var array = [1, 2, 3, 4],
isFindKey = /Key$/.test(methodName); func = _[methodName];
(function() {
var objects = [
{ 'a': 0, 'b': 0 },
{ 'a': 1, 'b': 1 },
{ 'a': 2, 'b': 2 }
];
var expected = ({ var objects = [
'find': [objects[1], undefined, objects[2], objects[1]], { 'a': 0, 'b': 0 },
'findLast': [objects[2], undefined, objects[2], objects[2]], { 'a': 1, 'b': 1 },
'findIndex': [1, -1, 2, 1], { 'a': 2, 'b': 2 }
'findLastIndex': [2, -1, 2, 2], ];
'findKey': ['1', undefined, '2', '1'],
'findLastKey': ['2', undefined, '2', '2']
})[methodName];
QUnit.test('should return the found value', function(assert) { var expected = ({
assert.expect(1); 'find': [objects[1], undefined, objects[2]],
'findIndex': [1, -1, 2],
'findKey': ['1', undefined, '2'],
'findLast': [objects[2], undefined, objects[2]],
'findLastIndex': [2, -1, 2],
'findLastKey': ['2', undefined, '2']
})[methodName];
assert.strictEqual(func(objects, function(object) { return object.a; }), QUnit.test('`_.' + methodName + '` should return the found value', function(
expected[0]); assert) {
}); assert.expect(1);
QUnit.test('should return `' + expected[1] + '` if value is not found', fu assert.strictEqual(func(objects, function(object) { return object.a; }), e
nction(assert) { xpected[0]);
assert.expect(1); });
assert.strictEqual(func(objects, function(object) { return object.a === QUnit.test('`_.' + methodName + '` should return `' + expected[1] + '` if va
3; }), expected[1]); lue is not found', function(assert) {
}); assert.expect(1);
QUnit.test('should work with a "_.matches" style `predicate`', function(as assert.strictEqual(func(objects, function(object) { return object.a === 3;
sert) { }), expected[1]);
assert.expect(1); });
assert.strictEqual(func(objects, { 'b': 2 }), expected[2]); QUnit.test('`_.' + methodName + '` should work with `_.matches` shorthands',
}); function(assert) {
assert.expect(1);
QUnit.test('should work with a "_.matchesProperty" style `predicate`', fun assert.strictEqual(func(objects, { 'b': 2 }), expected[2]);
ction(assert) { });
assert.expect(1);
assert.strictEqual(func(objects, ['b', 2]), expected[2]); QUnit.test('`_.' + methodName + '` should work with `_.matchesProperty` shor
}); thands', function(assert) {
assert.expect(1);
QUnit.test('should work with a "_.property" style `predicate`', function(a assert.strictEqual(func(objects, ['b', 2]), expected[2]);
ssert) { });
assert.expect(1);
assert.strictEqual(func(objects, 'b'), expected[3]); QUnit.test('`_.' + methodName + '` should work with `_.property` shorthands'
}); , function(assert) {
assert.expect(1);
QUnit.test('should return `' + expected[1] + '` for empty collections', fu assert.strictEqual(func(objects, 'b'), expected[0]);
nction(assert) { });
assert.expect(1);
var emptyValues = lodashStable.endsWith(methodName, 'Index') ? lodashSta QUnit.test('`_.' + methodName + '` should return `' + expected[1] + '` for e
ble.reject(empties, lodashStable.isPlainObject) : empties, mpty collections', function(assert) {
expecting = lodashStable.map(emptyValues, lodashStable.constant(expe assert.expect(1);
cted[1]));
var actual = lodashStable.map(emptyValues, function(value) { var emptyValues = lodashStable.endsWith(methodName, 'Index') ? lodashStabl
try { e.reject(empties, lodashStable.isPlainObject) : empties,
return func(value, { 'a': 3 }); expecting = lodashStable.map(emptyValues, lodashStable.constant(expect
} catch (e) {} ed[1]));
});
assert.deepEqual(actual, expecting); var actual = lodashStable.map(emptyValues, function(value) {
try {
return func(value, { 'a': 3 });
} catch (e) {}
}); });
}());
(function() { assert.deepEqual(actual, expecting);
var array = [1, 2, 3, 4]; });
QUnit.test('`_.' + methodName + '` should return an unwrapped value when imp
licitly chaining', function(assert) {
assert.expect(1);
var expected = ({ var expected = ({
'find': 1, 'find': 1,
'findLast': 4,
'findIndex': 0, 'findIndex': 0,
'findLastIndex': 3,
'findKey': '0', 'findKey': '0',
'findLast': 4,
'findLastIndex': 3,
'findLastKey': '3' 'findLastKey': '3'
})[methodName]; })[methodName];
QUnit.test('should return an unwrapped value when implicitly chaining', fu if (!isNpm) {
nction(assert) { assert.strictEqual(_(array)[methodName](), expected);
assert.expect(1); }
else {
skipAssert(assert);
}
});
if (!isNpm) { QUnit.test('`_.' + methodName + '` should return a wrapped value when explic
assert.strictEqual(_(array)[methodName](), expected); itly chaining', function(assert) {
} assert.expect(1);
else {
skipTest(assert);
}
});
QUnit.test('should return a wrapped value when explicitly chaining', funct if (!isNpm) {
ion(assert) { assert.ok(_(array).chain()[methodName]() instanceof _);
assert.expect(1); }
else {
skipAssert(assert);
}
});
if (!isNpm) { QUnit.test('`_.' + methodName + '` should not execute immediately when expli
assert.ok(_(array).chain()[methodName]() instanceof _); citly chaining', function(assert) {
} assert.expect(1);
else {
skipTest(assert);
}
});
QUnit.test('should not execute immediately when explicitly chaining', func if (!isNpm) {
tion(assert) { var wrapped = _(array).chain()[methodName]();
assert.expect(1); assert.strictEqual(wrapped.__wrapped__, array);
}
else {
skipAssert(assert);
}
});
if (!isNpm) { QUnit.test('`_.' + methodName + '` should work in a lazy sequence', function
var wrapped = _(array).chain()[methodName](); (assert) {
assert.strictEqual(wrapped.__wrapped__, array); assert.expect(2);
}
else { if (!isNpm) {
skipTest(assert); var largeArray = lodashStable.range(1, LARGE_ARRAY_SIZE + 1),
} smallArray = array;
lodashStable.times(2, function(index) {
var array = index ? largeArray : smallArray,
wrapped = _(array).filter(isEven);
assert.strictEqual(wrapped[methodName](), func(lodashStable.filter(arr
ay, isEven)));
});
}
else {
skipAssert(assert, 2);
}
});
});
_.each(['find', 'findIndex', 'findLast', 'findLastIndex'], function(methodName
) {
var func = _[methodName];
QUnit.test('`_.' + methodName + '` should provide correct `predicate` argume
nts for arrays', function(assert) {
assert.expect(1);
var args,
array = ['a'];
func(array, function() {
args || (args = slice.call(arguments));
}); });
QUnit.test('should work in a lazy sequence', function(assert) { assert.deepEqual(args, ['a', 0, array]);
assert.expect(2); });
});
if (!isNpm) { _.each(['find', 'findKey', 'findLast', 'findLastKey'], function(methodName) {
var largeArray = lodashStable.range(1, LARGE_ARRAY_SIZE + 1), var func = _[methodName];
smallArray = array;
lodashStable.times(2, function(index) { QUnit.test('`_.' + methodName + '` should work with an object for `collectio
var array = index ? largeArray : smallArray, n`', function(assert) {
wrapped = _(array).filter(isEven); assert.expect(1);
assert.strictEqual(wrapped[methodName](), func(lodashStable.filter(a var actual = func({ 'a': 1, 'b': 2, 'c': 3 }, function(n) {
rray, isEven))); return n < 3;
});
}
else {
skipTest(assert, 2);
}
}); });
}());
(function() {
var expected = ({ var expected = ({
'find': 1, 'find': 1,
'findLast': 2,
'findKey': 'a', 'findKey': 'a',
'findLast': 2,
'findLastKey': 'b' 'findLastKey': 'b'
})[methodName]; })[methodName];
if (expected != null) { assert.strictEqual(actual, expected);
QUnit.test('should work with an object for `collection`', function(asser });
t) {
assert.expect(1);
var actual = func({ 'a': 1, 'b': 2, 'c': 3 }, function(num) { QUnit.test('`_.' + methodName + '` should provide correct `predicate` argume
return num < 3; nts for objects', function(assert) {
}); assert.expect(1);
assert.strictEqual(actual, expected); var args,
}); object = { 'a': 1 };
}
}()); func(object, function() {
args || (args = slice.call(arguments));
});
assert.deepEqual(args, [1, 'a', object]);
});
}); });
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.find and lodash.findLast'); QUnit.module('lodash.find and lodash.findLast');
lodashStable.each(['find', 'findLast'], function(methodName) { lodashStable.each(['find', 'findLast'], function(methodName) {
var isFind = methodName == 'find'; var isFind = methodName == 'find';
QUnit.test('`_.' + methodName + '` should support shortcut fusion', function (assert) { QUnit.test('`_.' + methodName + '` should support shortcut fusion', function (assert) {
skipping to change at line 5297 skipping to change at line 6067
array = lodashStable.range(1, LARGE_ARRAY_SIZE + 1), array = lodashStable.range(1, LARGE_ARRAY_SIZE + 1),
iteratee = function(value) { mapCount++; return square(value); }, iteratee = function(value) { mapCount++; return square(value); },
predicate = function(value) { findCount++; return isEven(value); }, predicate = function(value) { findCount++; return isEven(value); },
actual = _(array).map(iteratee)[methodName](predicate); actual = _(array).map(iteratee)[methodName](predicate);
assert.strictEqual(findCount, isFind ? 2 : 1); assert.strictEqual(findCount, isFind ? 2 : 1);
assert.strictEqual(mapCount, isFind ? 2 : 1); assert.strictEqual(mapCount, isFind ? 2 : 1);
assert.strictEqual(actual, isFind ? 4 : square(LARGE_ARRAY_SIZE)); assert.strictEqual(actual, isFind ? 4 : square(LARGE_ARRAY_SIZE));
} }
else { else {
skipTest(assert, 3); skipAssert(assert, 3);
} }
}); });
}); });
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.find and lodash.includes');
lodashStable.each(['includes', 'find'], function(methodName) {
var func = _[methodName],
isIncludes = methodName == 'includes',
resolve = methodName == 'find' ? lodashStable.curry(lodashStable.eq) : i
dentity;
lodashStable.each({
'an `arguments` object': args,
'an array': [1, 2, 3]
},
function(collection, key) {
var values = lodashStable.toArray(collection);
QUnit.test('`_.' + methodName + '` should work with ' + key + ' and a posi
tive `fromIndex`', function(assert) {
assert.expect(1);
var expected = [
isIncludes || values[2],
isIncludes ? false : undefined
];
var actual = [
func(collection, resolve(values[2]), 2),
func(collection, resolve(values[1]), 2)
];
assert.deepEqual(actual, expected);
});
QUnit.test('`_.' + methodName + '` should work with ' + key + ' and a `fro
mIndex` >= `length`', function(assert) {
assert.expect(1);
var indexes = [4, 6, Math.pow(2, 32), Infinity];
var expected = lodashStable.map(indexes, function() {
var result = isIncludes ? false : undefined;
return [result, result, result];
});
var actual = lodashStable.map(indexes, function(fromIndex) {
return [
func(collection, resolve(1), fromIndex),
func(collection, resolve(undefined), fromIndex),
func(collection, resolve(''), fromIndex)
];
});
assert.deepEqual(actual, expected);
});
QUnit.test('`_.' + methodName + '` should work with ' + key + ' and treat
falsey `fromIndex` values as `0`', function(assert) {
assert.expect(1);
var expected = lodashStable.map(falsey, lodashStable.constant(isIncludes
|| values[0]));
var actual = lodashStable.map(falsey, function(fromIndex) {
return func(collection, resolve(values[0]), fromIndex);
});
assert.deepEqual(actual, expected);
});
QUnit.test('`_.' + methodName + '` should work with ' + key + ' and coerce
`fromIndex` to an integer', function(assert) {
assert.expect(1);
var expected = [
isIncludes || values[0],
isIncludes || values[0],
isIncludes ? false : undefined
];
var actual = [
func(collection, resolve(values[0]), 0.1),
func(collection, resolve(values[0]), NaN),
func(collection, resolve(values[0]), '1')
];
assert.deepEqual(actual, expected);
});
QUnit.test('`_.' + methodName + '` should work with ' + key + ' and a nega
tive `fromIndex`', function(assert) {
assert.expect(1);
var expected = [
isIncludes || values[2],
isIncludes ? false : undefined
];
var actual = [
func(collection, resolve(values[2]), -1),
func(collection, resolve(values[1]), -1)
];
assert.deepEqual(actual, expected);
});
QUnit.test('`_.' + methodName + '` should work with ' + key + ' and a nega
tive `fromIndex` <= `-length`', function(assert) {
assert.expect(1);
var indexes = [-4, -6, -Infinity],
expected = lodashStable.map(indexes, lodashStable.constant(isInclude
s || values[0]));
var actual = lodashStable.map(indexes, function(fromIndex) {
return func(collection, resolve(values[0]), fromIndex);
});
assert.deepEqual(actual, expected);
});
});
});
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.findIndex and lodash.indexOf');
lodashStable.each(['findIndex', 'indexOf'], function(methodName) {
var array = [1, 2, 3, 1, 2, 3],
func = _[methodName],
resolve = methodName == 'findIndex' ? lodashStable.curry(lodashStable.eq
) : identity;
QUnit.test('`_.' + methodName + '` should return the index of the first matc
hed value', function(assert) {
assert.expect(1);
assert.strictEqual(func(array, resolve(3)), 2);
});
QUnit.test('`_.' + methodName + '` should work with a positive `fromIndex`',
function(assert) {
assert.expect(1);
assert.strictEqual(func(array, resolve(1), 2), 3);
});
QUnit.test('`_.' + methodName + '` should work with a `fromIndex` >= `length
`', function(assert) {
assert.expect(1);
var values = [6, 8, Math.pow(2, 32), Infinity],
expected = lodashStable.map(values, lodashStable.constant([-1, -1, -1]
));
var actual = lodashStable.map(values, function(fromIndex) {
return [
func(array, resolve(undefined), fromIndex),
func(array, resolve(1), fromIndex),
func(array, resolve(''), fromIndex)
];
});
assert.deepEqual(actual, expected);
});
QUnit.test('`_.' + methodName + '` should work with a negative `fromIndex`',
function(assert) {
assert.expect(1);
assert.strictEqual(func(array, resolve(2), -3), 4);
});
QUnit.test('`_.' + methodName + '` should work with a negative `fromIndex` <
= `-length`', function(assert) {
assert.expect(1);
var values = [-6, -8, -Infinity],
expected = lodashStable.map(values, stubZero);
var actual = lodashStable.map(values, function(fromIndex) {
return func(array, resolve(1), fromIndex);
});
assert.deepEqual(actual, expected);
});
QUnit.test('`_.' + methodName + '` should treat falsey `fromIndex` values as
`0`', function(assert) {
assert.expect(1);
var expected = lodashStable.map(falsey, stubZero);
var actual = lodashStable.map(falsey, function(fromIndex) {
return func(array, resolve(1), fromIndex);
});
assert.deepEqual(actual, expected);
});
QUnit.test('`_.' + methodName + '` should coerce `fromIndex` to an integer',
function(assert) {
assert.expect(1);
assert.strictEqual(func(array, resolve(2), 1.2), 1);
});
});
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.findLast');
(function() {
var resolve = lodashStable.curry(lodashStable.eq);
lodashStable.each({
'an `arguments` object': args,
'an array': [1, 2, 3]
},
function(collection, key) {
var values = lodashStable.toArray(collection);
QUnit.test('should work with ' + key + ' and a positive `fromIndex`', func
tion(assert) {
assert.expect(1);
var expected = [
values[1],
undefined
];
var actual = [
_.findLast(collection, resolve(values[1]), 1),
_.findLast(collection, resolve(values[2]), 1)
];
assert.deepEqual(actual, expected);
});
QUnit.test('should work with ' + key + ' and a `fromIndex` >= `length`', f
unction(assert) {
assert.expect(1);
var indexes = [4, 6, Math.pow(2, 32), Infinity];
var expected = lodashStable.map(indexes, lodashStable.constant([values[0
], undefined, undefined]));
var actual = lodashStable.map(indexes, function(fromIndex) {
return [
_.findLast(collection, resolve(1), fromIndex),
_.findLast(collection, resolve(undefined), fromIndex),
_.findLast(collection, resolve(''), fromIndex)
];
});
assert.deepEqual(actual, expected);
});
QUnit.test('should work with ' + key + ' and treat falsey `fromIndex` valu
es correctly', function(assert) {
assert.expect(1);
var expected = lodashStable.map(falsey, function(value) {
return value === undefined ? values[3] : undefined;
});
var actual = lodashStable.map(falsey, function(fromIndex) {
return _.findLast(collection, resolve(values[3]), fromIndex);
});
assert.deepEqual(actual, expected);
});
QUnit.test('should work with ' + key + ' and coerce `fromIndex` to an inte
ger', function(assert) {
assert.expect(1);
var expected = [
values[0],
values[0],
undefined
];
var actual = [
_.findLast(collection, resolve(values[0]), 0.1),
_.findLast(collection, resolve(values[0]), NaN),
_.findLast(collection, resolve(values[2]), '1')
];
assert.deepEqual(actual, expected);
});
QUnit.test('should work with ' + key + ' and a negative `fromIndex`', func
tion(assert) {
assert.expect(1);
var expected = [
values[1],
undefined
];
var actual = [
_.findLast(collection, resolve(values[1]), -2),
_.findLast(collection, resolve(values[2]), -2)
];
assert.deepEqual(actual, expected);
});
QUnit.test('should work with ' + key + ' and a negative `fromIndex` <= `-l
ength`', function(assert) {
assert.expect(1);
var indexes = [-4, -6, -Infinity],
expected = lodashStable.map(indexes, lodashStable.constant(values[0]
));
var actual = lodashStable.map(indexes, function(fromIndex) {
return _.findLast(collection, resolve(values[0]), fromIndex);
});
assert.deepEqual(actual, expected);
});
});
}());
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.flip'); QUnit.module('lodash.flip');
(function() { (function() {
function fn() { function fn() {
return slice.call(arguments); return slice.call(arguments);
} }
QUnit.test('should flip arguments provided to `func`', function(assert) { QUnit.test('should flip arguments provided to `func`', function(assert) {
assert.expect(1); assert.expect(1);
var flipped = _.flip(fn); var flipped = _.flip(fn);
assert.deepEqual(flipped('a', 'b', 'c', 'd'), ['d', 'c', 'b', 'a']); assert.deepEqual(flipped('a', 'b', 'c', 'd'), ['d', 'c', 'b', 'a']);
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.flatMap'); QUnit.module('lodash.flatMapDepth');
(function() { (function() {
var array = [1, 2, 3, 4]; var array = [1, [2, [3, [4]], 5]];
QUnit.test('should use a default `depth` of `1`', function(assert) {
assert.expect(1);
assert.deepEqual(_.flatMapDepth(array, identity), [1, 2, [3, [4]], 5]);
});
QUnit.test('should use `_.identity` when `iteratee` is nullish', function(as
sert) {
assert.expect(1);
var values = [, null, undefined],
expected = lodashStable.map(values, lodashStable.constant([1, 2, [3, [
4]], 5]));
var actual = lodashStable.map(values, function(value, index) {
return index ? _.flatMapDepth(array, value) : _.flatMapDepth(array);
});
assert.deepEqual(actual, expected);
});
QUnit.test('should treat a `depth` of < `1` as a shallow clone', function(as
sert) {
assert.expect(2);
lodashStable.each([-1, 0], function(depth) {
assert.deepEqual(_.flatMapDepth(array, identity, depth), [1, [2, [3, [4]
], 5]]);
});
});
QUnit.test('should coerce `depth` to an integer', function(assert) {
assert.expect(1);
assert.deepEqual(_.flatMapDepth(array, identity, 2.2), [1, 2, 3, [4], 5]);
});
}());
/*--------------------------------------------------------------------------*/
QUnit.module('flatMap methods');
lodashStable.each(['flatMap', 'flatMapDeep', 'flatMapDepth'], function(methodN
ame) {
var func = _[methodName],
array = [1, 2, 3, 4];
function duplicate(n) { function duplicate(n) {
return [n, n]; return [n, n];
} }
QUnit.test('should map values in `array` to a new flattened array', function (assert) { QUnit.test('`_.' + methodName + '` should map values in `array` to a new fla ttened array', function(assert) {
assert.expect(1); assert.expect(1);
var actual = _.flatMap(array, duplicate), var actual = func(array, duplicate),
expected = lodashStable.flatten(lodashStable.map(array, duplicate)); expected = lodashStable.flatten(lodashStable.map(array, duplicate));
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
}); });
QUnit.test('should work in a lazy sequence', function(assert) { QUnit.test('`_.' + methodName + '` should work with `_.property` shorthands'
assert.expect(2); , function(assert) {
assert.expect(1);
if (!isNpm) { var objects = [{ 'a': [1, 2] }, { 'a': [3, 4] }];
var largeArray = lodashStable.range(LARGE_ARRAY_SIZE), assert.deepEqual(func(objects, 'a'), array);
smallArray = array; });
lodashStable.times(2, function(index) { QUnit.test('`_.' + methodName + '` should iterate over own string keyed prop
var array = index ? largeArray : smallArray, erties of objects', function(assert) {
actual = _(array).filter(isEven).flatMap(duplicate).take(2).value( assert.expect(1);
);
assert.deepEqual(actual, _.take(_.flatMap(_.filter(array, isEven), dup function Foo() {
licate), 2)); this.a = [1, 2];
});
}
else {
skipTest(assert, 2);
} }
Foo.prototype.b = [3, 4];
var actual = func(new Foo, identity);
assert.deepEqual(actual, [1, 2]);
}); });
}());
QUnit.test('`_.' + methodName + '` should use `_.identity` when `iteratee` i
s nullish', function(assert) {
assert.expect(2);
var array = [[1, 2], [3, 4]],
object = { 'a': [1, 2], 'b': [3, 4] },
values = [, null, undefined],
expected = lodashStable.map(values, lodashStable.constant([1, 2, 3, 4]
));
lodashStable.each([array, object], function(collection) {
var actual = lodashStable.map(values, function(value, index) {
return index ? func(collection, value) : func(collection);
});
assert.deepEqual(actual, expected);
});
});
QUnit.test('`_.' + methodName + '` should accept a falsey `collection`', fun
ction(assert) {
assert.expect(1);
var expected = lodashStable.map(falsey, stubArray);
var actual = lodashStable.map(falsey, function(collection, index) {
try {
return index ? func(collection) : func();
} catch (e) {}
});
assert.deepEqual(actual, expected);
});
QUnit.test('`_.' + methodName + '` should treat number values for `collectio
n` as empty', function(assert) {
assert.expect(1);
assert.deepEqual(func(1), []);
});
QUnit.test('`_.' + methodName + '` should work with objects with non-number
length properties', function(assert) {
assert.expect(1);
var object = { 'length': [1, 2] };
assert.deepEqual(func(object, identity), [1, 2]);
});
});
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('flatten methods'); QUnit.module('lodash.flattenDepth');
(function() { (function() {
var args = arguments; var array = [1, [2, [3, [4]], 5]];
QUnit.test('should perform a shallow flatten', function(assert) { QUnit.test('should use a default `depth` of `1`', function(assert) {
assert.expect(1); assert.expect(1);
var array = [[['a']], [['b']]]; assert.deepEqual(_.flattenDepth(array), [1, 2, [3, [4]], 5]);
assert.deepEqual(_.flatten(array), [['a'], ['b']]);
}); });
QUnit.test('should flatten `arguments` objects', function(assert) { QUnit.test('should treat a `depth` of < `1` as a shallow clone', function(as sert) {
assert.expect(2); assert.expect(2);
lodashStable.each([-1, 0], function(depth) {
assert.deepEqual(_.flattenDepth(array, depth), [1, [2, [3, [4]], 5]]);
});
});
QUnit.test('should coerce `depth` to an integer', function(assert) {
assert.expect(1);
assert.deepEqual(_.flattenDepth(array, 2.2), [1, 2, 3, [4], 5]);
});
}());
/*--------------------------------------------------------------------------*/
QUnit.module('flatten methods');
(function() {
var array = [1, [2, [3, [4]], 5]],
methodNames = ['flatten', 'flattenDeep', 'flattenDepth'];
QUnit.test('should flatten `arguments` objects', function(assert) {
assert.expect(3);
var array = [args, [args]]; var array = [args, [args]];
assert.deepEqual(_.flatten(array), [1, 2, 3, args]); assert.deepEqual(_.flatten(array), [1, 2, 3, args]);
assert.deepEqual(_.flattenDeep(array), [1, 2, 3, 1, 2, 3]); assert.deepEqual(_.flattenDeep(array), [1, 2, 3, 1, 2, 3]);
assert.deepEqual(_.flattenDepth(array, 2), [1, 2, 3, 1, 2, 3]);
}); });
QUnit.test('should treat sparse arrays as dense', function(assert) { QUnit.test('should treat sparse arrays as dense', function(assert) {
assert.expect(6); assert.expect(6);
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);
lodashStable.each([_.flatten(array), _.flatten(array, true), _.flattenDeep lodashStable.each(methodNames, function(methodName) {
(array)], function(actual) { var actual = _[methodName](array);
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
assert.ok('4' in actual); assert.ok('4' in actual);
}); });
}); });
QUnit.test('should flatten objects with a truthy `Symbol.isConcatSpreadable`
value', function(assert) {
assert.expect(1);
if (Symbol && Symbol.isConcatSpreadable) {
var object = { '0': 'a', 'length': 1 },
array = [object],
expected = lodashStable.map(methodNames, lodashStable.constant(['a']
));
object[Symbol.isConcatSpreadable] = true;
var actual = lodashStable.map(methodNames, function(methodName) {
return _[methodName](array);
});
assert.deepEqual(actual, expected);
}
else {
skipAssert(assert);
}
});
QUnit.test('should work with extremely large arrays', function(assert) { QUnit.test('should work with extremely large arrays', function(assert) {
assert.expect(3); assert.expect(3);
// Test in modern browsers only to avoid browser hangs.
lodashStable.times(3, function(index) { lodashStable.times(3, function(index) {
if (freeze) { var expected = Array(5e5);
var expected = Array(5e5); try {
var func = _.flatten;
try { if (index == 1) {
if (index) { func = _.flattenDeep;
var actual = actual == 1 ? _.flatten([expected], true) : _.flatten } else if (index == 2) {
Deep([expected]); func = _.flattenDepth;
} else {
actual = _.flatten(expected);
}
assert.deepEqual(actual, expected);
} catch (e) {
assert.ok(false, e.message);
} }
} assert.deepEqual(func([expected]), expected);
else { } catch (e) {
skipTest(assert); assert.ok(false, e.message);
} }
}); });
}); });
QUnit.test('should work with empty arrays', function(assert) { QUnit.test('should work with empty arrays', function(assert) {
assert.expect(2); assert.expect(3);
var array = [[], [[]], [[], [[[]]]]]; var array = [[], [[]], [[], [[[]]]]];
assert.deepEqual(_.flatten(array), [[], [], [[[]]]]); assert.deepEqual(_.flatten(array), [[], [], [[[]]]]);
assert.deepEqual(_.flattenDeep(array), []); assert.deepEqual(_.flattenDeep(array), []);
assert.deepEqual(_.flattenDepth(array, 2), [[[]]]);
}); });
QUnit.test('should support flattening of nested arrays', function(assert) { QUnit.test('should support flattening of nested arrays', function(assert) {
assert.expect(2); assert.expect(3);
var array = [1, [2, 3], 4, [[5]]];
assert.deepEqual(_.flatten(array), [1, 2, 3, 4, [5]]); assert.deepEqual(_.flatten(array), [1, 2, [3, [4]], 5]);
assert.deepEqual(_.flattenDeep(array), [1, 2, 3, 4, 5]); assert.deepEqual(_.flattenDeep(array), [1, 2, 3, 4, 5]);
assert.deepEqual(_.flattenDepth(array, 2), [1, 2, 3, [4], 5]);
}); });
QUnit.test('should return an empty array for non array-like objects', functi on(assert) { QUnit.test('should return an empty array for non array-like objects', functi on(assert) {
assert.expect(3); assert.expect(3);
var expected = []; var expected = [],
nonArray = { '0': 'a' };
assert.deepEqual(_.flatten({ 'a': 1 }), expected); assert.deepEqual(_.flatten(nonArray), expected);
assert.deepEqual(_.flatten({ 'a': 1 }, true), expected); assert.deepEqual(_.flattenDeep(nonArray), expected);
assert.deepEqual(_.flattenDeep({ 'a': 1 }), expected); assert.deepEqual(_.flattenDepth(nonArray, 2), expected);
}); });
QUnit.test('should return a wrapped value when chaining', function(assert) { QUnit.test('should return a wrapped value when chaining', function(assert) {
assert.expect(4); assert.expect(6);
if (!isNpm) { if (!isNpm) {
var wrapped = _([1, [2], [3, [4]]]), var wrapped = _(array),
actual = wrapped.flatten(); actual = wrapped.flatten();
assert.ok(actual instanceof _); assert.ok(actual instanceof _);
assert.deepEqual(actual.value(), [1, 2, 3, [4]]); assert.deepEqual(actual.value(), [1, 2, [3, [4]], 5]);
actual = wrapped.flattenDeep(); actual = wrapped.flattenDeep();
assert.ok(actual instanceof _); assert.ok(actual instanceof _);
assert.deepEqual(actual.value(), [1, 2, 3, 4]); assert.deepEqual(actual.value(), [1, 2, 3, 4, 5]);
actual = wrapped.flattenDepth(2);
assert.ok(actual instanceof _);
assert.deepEqual(actual.value(), [1, 2, 3, [4], 5]);
} }
else { else {
skipTest(assert, 4); skipAssert(assert, 6);
} }
}); });
}(1, 2, 3)); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('flow methods'); QUnit.module('flow methods');
lodashStable.each(['flow', 'flowRight'], function(methodName) { lodashStable.each(['flow', 'flowRight'], function(methodName) {
var func = _[methodName], var func = _[methodName],
isFlow = methodName == 'flow'; isFlow = methodName == 'flow';
QUnit.test('`_.' + methodName + '` should supply each function with the retu rn value of the previous', function(assert) { QUnit.test('`_.' + methodName + '` should supply each function with the retu rn value of the previous', function(assert) {
skipping to change at line 5493 skipping to change at line 6695
assert.strictEqual(combined(1, 2), '9.0'); assert.strictEqual(combined(1, 2), '9.0');
}); });
QUnit.test('`_.' + methodName + '` should return a new function', function(a ssert) { QUnit.test('`_.' + methodName + '` should return a new function', function(a ssert) {
assert.expect(1); assert.expect(1);
assert.notStrictEqual(func(noop), noop); assert.notStrictEqual(func(noop), noop);
}); });
QUnit.test('`_.' + methodName + '` should return an identity function when n QUnit.test('`_.' + methodName + '` should return an identity function when n
o arguments are provided', function(assert) { o arguments are given', function(assert) {
assert.expect(3); assert.expect(6);
var combined = func();
try { _.times(2, function(index) {
assert.strictEqual(combined('a'), 'a'); try {
} catch (e) { var combined = index ? func([]) : func();
assert.ok(false, e.message); assert.strictEqual(combined('a'), 'a');
} } catch (e) {
assert.strictEqual(combined.length, 0); assert.ok(false, e.message);
assert.notStrictEqual(combined, identity); }
assert.strictEqual(combined.length, 0);
assert.notStrictEqual(combined, identity);
});
}); });
QUnit.test('`_.' + methodName + '` should work with a curried function and ` _.head`', function(assert) { QUnit.test('`_.' + methodName + '` should work with a curried function and ` _.head`', function(assert) {
assert.expect(1); assert.expect(1);
var curried = _.curry(identity); var curried = _.curry(identity);
var combined = isFlow var combined = isFlow
? func(_.head, curried) ? func(_.head, curried)
: func(curried, _.head); : func(curried, _.head);
skipping to change at line 5553 skipping to change at line 6756
: func(take3, _.compact, filter3, map3); : func(take3, _.compact, filter3, map3);
filterCount = mapCount = 0; filterCount = mapCount = 0;
assert.deepEqual(combined(array), [4, 16]); assert.deepEqual(combined(array), [4, 16]);
if (!isNpm && WeakMap && WeakMap.name) { if (!isNpm && WeakMap && WeakMap.name) {
assert.strictEqual(filterCount, 5, 'filterCount'); assert.strictEqual(filterCount, 5, 'filterCount');
assert.strictEqual(mapCount, 5, 'mapCount'); assert.strictEqual(mapCount, 5, 'mapCount');
} }
else { else {
skipTest(assert, 2); skipAssert(assert, 2);
} }
_.filter = filter1; _.filter = filter1;
_.map = map1; _.map = map1;
_.take = take1; _.take = take1;
}); });
}); });
QUnit.test('`_.' + methodName + '` should work with curried functions with p laceholders', function(assert) { QUnit.test('`_.' + methodName + '` should work with curried functions with p laceholders', function(assert) {
assert.expect(1); assert.expect(1);
skipping to change at line 5583 skipping to change at line 6786
}); });
QUnit.test('`_.' + methodName + '` should return a wrapped value when chaini ng', function(assert) { QUnit.test('`_.' + methodName + '` should return a wrapped value when chaini ng', function(assert) {
assert.expect(1); assert.expect(1);
if (!isNpm) { if (!isNpm) {
var wrapped = _(noop)[methodName](); var wrapped = _(noop)[methodName]();
assert.ok(wrapped instanceof _); assert.ok(wrapped instanceof _);
} }
else { else {
skipTest(assert); skipAssert(assert);
} }
}); });
}); });
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.forEach'); QUnit.module('lodash.forEach');
(function() { (function() {
QUnit.test('should be aliased', function(assert) { QUnit.test('should be aliased', function(assert) {
skipping to change at line 5619 skipping to change at line 6822
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('forIn methods'); QUnit.module('forIn methods');
lodashStable.each(['forIn', 'forInRight'], function(methodName) { lodashStable.each(['forIn', 'forInRight'], function(methodName) {
var func = _[methodName]; var func = _[methodName];
QUnit.test('`_.' + methodName + '` iterates over inherited properties', func tion(assert) { QUnit.test('`_.' + methodName + '` iterates over inherited string keyed prop erties', function(assert) {
assert.expect(1); 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); });
assert.deepEqual(keys.sort(), ['a', 'b']); assert.deepEqual(keys.sort(), ['a', 'b']);
}); });
}); });
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('forOwn methods'); QUnit.module('forOwn methods');
lodashStable.each(['forOwn', 'forOwnRight'], function(methodName) { lodashStable.each(['forOwn', 'forOwnRight'], function(methodName) {
var func = _[methodName]; var func = _[methodName];
QUnit.test('should iterate over `length` properties', function(assert) { QUnit.test('`_.' + methodName + '` should iterate over `length` properties', function(assert) {
assert.expect(1); 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); });
assert.deepEqual(props.sort(), ['0', '1', 'length']); assert.deepEqual(props.sort(), ['0', '1', 'length']);
}); });
}); });
skipping to change at line 5751 skipping to change at line 6956
var rightMethods = [ var rightMethods = [
'findLast', 'findLast',
'findLastIndex', 'findLastIndex',
'findLastKey', 'findLastKey',
'forEachRight', 'forEachRight',
'forInRight', 'forInRight',
'forOwnRight' 'forOwnRight'
]; ];
var unwrappedMethods = [ var unwrappedMethods = [
'each',
'eachRight',
'every', 'every',
'find', 'find',
'findIndex', 'findIndex',
'findKey', 'findKey',
'findLast', 'findLast',
'findLastIndex', 'findLastIndex',
'findLastKey', 'findLastKey',
'forEach', 'forEach',
'forEachRight', 'forEachRight',
'forIn', 'forIn',
skipping to change at line 5776 skipping to change at line 6983
'min', 'min',
'minBy', 'minBy',
'some' 'some'
]; ];
lodashStable.each(methods, function(methodName) { lodashStable.each(methods, function(methodName) {
var array = [1, 2, 3], var array = [1, 2, 3],
func = _[methodName], func = _[methodName],
isBy = /(^partition|By)$/.test(methodName), isBy = /(^partition|By)$/.test(methodName),
isFind = /^find/.test(methodName), isFind = /^find/.test(methodName),
isOmitPick = /^(?:omit|pick)By$/.test(methodName),
isSome = methodName == 'some'; isSome = methodName == 'some';
QUnit.test('`_.' + methodName + '` should provide the correct iteratee arg uments', function(assert) { QUnit.test('`_.' + methodName + '` should provide correct iteratee argumen ts', function(assert) {
assert.expect(1); assert.expect(1);
if (func) { if (func) {
var args, var args,
expected = [1, 0, array]; expected = [1, 0, array];
func(array, function() { func(array, function() {
args || (args = slice.call(arguments)); args || (args = slice.call(arguments));
}); });
if (lodashStable.includes(rightMethods, methodName)) { if (lodashStable.includes(rightMethods, methodName)) {
expected[0] = 3; expected[0] = 3;
expected[1] = 2; expected[1] = 2;
} }
if (lodashStable.includes(objectMethods, methodName)) { if (lodashStable.includes(objectMethods, methodName)) {
expected[1] += ''; expected[1] += '';
} }
if (isBy) { if (isBy) {
expected.length = 1; expected.length = isOmitPick ? 2 : 1;
} }
assert.deepEqual(args, expected); assert.deepEqual(args, expected);
} }
else { else {
skipTest(assert); skipAssert(assert);
} }
}); });
QUnit.test('`_.' + methodName + '` should treat sparse arrays as dense', f unction(assert) { QUnit.test('`_.' + methodName + '` should treat sparse arrays as dense', f unction(assert) {
assert.expect(1); assert.expect(1);
if (func) { if (func) {
var array = [1]; var array = [1];
array[2] = 3; array[2] = 3;
var expected = [[1, 0, array], [undefined, 1, array], [3, 2, array]]; var expected = lodashStable.includes(objectMethods, methodName)
? [[1, '0', array], [undefined, '1', array], [3, '2', array]]
: [[1, 0, array], [undefined, 1, array], [3, 2, array]];
if (isBy) { if (isBy) {
expected = lodashStable.map(expected, function(args) { expected = lodashStable.map(expected, function(args) {
return args.slice(0, 1); return args.slice(0, isOmitPick ? 2 : 1);
}); });
} }
else if (lodashStable.includes(objectMethods, methodName)) { else if (lodashStable.includes(objectMethods, methodName)) {
expected = lodashStable.map(expected, function(args) { expected = lodashStable.map(expected, function(args) {
args[1] += ''; args[1] += '';
return args; return args;
}); });
} }
if (lodashStable.includes(rightMethods, methodName)) { if (lodashStable.includes(rightMethods, methodName)) {
expected.reverse(); expected.reverse();
} }
var argsList = []; var argsList = [];
func(array, function() { func(array, function() {
argsList.push(slice.call(arguments)); argsList.push(slice.call(arguments));
return !(isFind || isSome); return !(isFind || isSome);
}); });
assert.deepEqual(argsList, expected); assert.deepEqual(argsList, expected);
} }
else { else {
skipTest(assert); skipAssert(assert);
} }
}); });
}); });
lodashStable.each(lodashStable.difference(methods, objectMethods), function( methodName) { lodashStable.each(lodashStable.difference(methods, objectMethods), function( methodName) {
var array = [1, 2, 3], var array = [1, 2, 3],
func = _[methodName], func = _[methodName],
isEvery = methodName == 'every'; isEvery = methodName == 'every';
array.a = 1; array.a = 1;
skipping to change at line 5863 skipping to change at line 7073
if (func) { if (func) {
var keys = []; var keys = [];
func(array, function(value, key) { func(array, function(value, key) {
keys.push(key); keys.push(key);
return isEvery; return isEvery;
}); });
assert.notOk(lodashStable.includes(keys, 'a')); assert.notOk(lodashStable.includes(keys, 'a'));
} }
else { else {
skipTest(assert); skipAssert(assert);
} }
}); });
}); });
lodashStable.each(lodashStable.difference(methods, unwrappedMethods), functi on(methodName) { lodashStable.each(lodashStable.difference(methods, unwrappedMethods), functi on(methodName) {
var array = [1, 2, 3], var array = [1, 2, 3],
func = _[methodName],
isBaseEach = methodName == '_baseEach'; isBaseEach = methodName == '_baseEach';
QUnit.test('`_.' + methodName + '` should return a wrapped value when impl icitly chaining', function(assert) { QUnit.test('`_.' + methodName + '` should return a wrapped value when impl icitly chaining', function(assert) {
assert.expect(1); assert.expect(1);
if (!(isBaseEach || isNpm)) { if (!(isBaseEach || isNpm)) {
var wrapped = _(array)[methodName](noop); var wrapped = _(array)[methodName](noop);
assert.ok(wrapped instanceof _); assert.ok(wrapped instanceof _);
} }
else { else {
skipTest(assert); skipAssert(assert);
} }
}); });
}); });
lodashStable.each(unwrappedMethods, function(methodName) { lodashStable.each(unwrappedMethods, function(methodName) {
var array = [1, 2, 3], var array = [1, 2, 3];
func = _[methodName];
QUnit.test('`_.' + methodName + '` should return an unwrapped value when i mplicitly chaining', function(assert) { QUnit.test('`_.' + methodName + '` should return an unwrapped value when i mplicitly chaining', function(assert) {
assert.expect(1); assert.expect(1);
if (!isNpm) { if (!isNpm) {
var actual = _(array)[methodName](noop); var actual = _(array)[methodName](noop);
assert.notOk(actual instanceof _); assert.notOk(actual instanceof _);
} }
else { else {
skipTest(assert); skipAssert(assert);
} }
}); });
QUnit.test('`_.' + methodName + '` should return a wrapped value when expl icitly chaining', function(assert) { QUnit.test('`_.' + methodName + '` should return a wrapped value when expl icitly chaining', function(assert) {
assert.expect(2); assert.expect(2);
if (!isNpm) { if (!isNpm) {
var wrapped = _(array).chain(), var wrapped = _(array).chain(),
actual = wrapped[methodName](noop); actual = wrapped[methodName](noop);
assert.ok(actual instanceof _); assert.ok(actual instanceof _);
assert.notStrictEqual(actual, wrapped); assert.notStrictEqual(actual, wrapped);
} }
else { else {
skipTest(assert, 2); skipAssert(assert, 2);
} }
}); });
}); });
lodashStable.each(lodashStable.difference(methods, arrayMethods, forInMethod s), function(methodName) { lodashStable.each(lodashStable.difference(methods, arrayMethods, forInMethod s), function(methodName) {
var array = [1, 2, 3], var func = _[methodName];
func = _[methodName];
QUnit.test('`_.' + methodName + '` iterates over own properties of objects ', function(assert) { QUnit.test('`_.' + methodName + '` iterates over own string keyed properti es of objects', function(assert) {
assert.expect(1); assert.expect(1);
function Foo() { this.a = 1; } function Foo() {
this.a = 1;
}
Foo.prototype.b = 2; Foo.prototype.b = 2;
if (func) { if (func) {
var values = []; var values = [];
func(new Foo, function(value) { values.push(value); }); func(new Foo, function(value) { values.push(value); });
assert.deepEqual(values, [1]); assert.deepEqual(values, [1]);
} }
else { else {
skipTest(assert); skipAssert(assert);
} }
}); });
}); });
lodashStable.each(iterationMethods, function(methodName) { lodashStable.each(iterationMethods, function(methodName) {
var array = [1, 2, 3], var array = [1, 2, 3],
func = _[methodName]; func = _[methodName];
QUnit.test('`_.' + methodName + '` should return the collection', function (assert) { QUnit.test('`_.' + methodName + '` should return the collection', function (assert) {
assert.expect(1); assert.expect(1);
if (func) { if (func) {
assert.strictEqual(func(array, Boolean), array); assert.strictEqual(func(array, Boolean), array);
} }
else { else {
skipTest(assert); skipAssert(assert);
} }
}); });
}); });
lodashStable.each(collectionMethods, function(methodName) { lodashStable.each(collectionMethods, function(methodName) {
var func = _[methodName]; var func = _[methodName];
QUnit.test('`_.' + methodName + '` should use `isArrayLike` to determine w hether a value is array-like', function(assert) { QUnit.test('`_.' + methodName + '` should use `isArrayLike` to determine w hether a value is array-like', function(assert) {
assert.expect(3); assert.expect(3);
if (func) { if (func) {
var isIteratedAsObject = function(object) { var isIteratedAsObject = function(object) {
var result = false; var result = false;
func(object, function() { result = true; }, 0); func(object, function() { result = true; }, 0);
return result; return result;
}; };
var values = [-1, '1', 1.1, Object(1), MAX_SAFE_INTEGER + 1], var values = [-1, '1', 1.1, Object(1), MAX_SAFE_INTEGER + 1],
expected = lodashStable.map(values, alwaysTrue); expected = lodashStable.map(values, stubTrue);
var actual = lodashStable.map(values, function(length) { var actual = lodashStable.map(values, function(length) {
return isIteratedAsObject({ 'length': length }); return isIteratedAsObject({ 'length': length });
}); });
var Foo = function(a) {}; var Foo = function(a) {};
Foo.a = 1; Foo.a = 1;
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
assert.ok(isIteratedAsObject(Foo)); assert.ok(isIteratedAsObject(Foo));
assert.notOk(isIteratedAsObject({ 'length': 0 })); assert.notOk(isIteratedAsObject({ 'length': 0 }));
} }
else { else {
skipTest(assert, 3); skipAssert(assert, 3);
} }
}); });
}); });
lodashStable.each(methods, function(methodName) { lodashStable.each(methods, function(methodName) {
var array = [1, 2, 3], var func = _[methodName],
func = _[methodName],
isFind = /^find/.test(methodName), isFind = /^find/.test(methodName),
isSome = methodName == 'some', isSome = methodName == 'some',
isReduce = /^reduce/.test(methodName); isReduce = /^reduce/.test(methodName);
QUnit.test('`_.' + methodName + '` should ignore changes to `array.length` ', function(assert) { QUnit.test('`_.' + methodName + '` should ignore changes to `length`', fun ction(assert) {
assert.expect(1); assert.expect(1);
if (func) { if (func) {
var count = 0, var count = 0,
array = [1]; array = [1];
func(array, function() { func(array, function() {
if (++count == 1) { if (++count == 1) {
array.push(2); array.push(2);
} }
return !(isFind || isSome); return !(isFind || isSome);
}, isReduce ? array : null); }, isReduce ? array : null);
assert.strictEqual(count, 1); assert.strictEqual(count, 1);
} }
else { else {
skipTest(assert); skipAssert(assert);
} }
}); });
}); });
lodashStable.each(lodashStable.difference(lodashStable.union(methods, collec tionMethods), arrayMethods), function(methodName) { lodashStable.each(lodashStable.difference(lodashStable.union(methods, collec tionMethods), arrayMethods), function(methodName) {
var func = _[methodName], var func = _[methodName],
isFind = /^find/.test(methodName), isFind = /^find/.test(methodName),
isSome = methodName == 'some', isSome = methodName == 'some',
isReduce = /^reduce/.test(methodName); isReduce = /^reduce/.test(methodName);
skipping to change at line 6040 skipping to change at line 7248
func(object, function() { func(object, function() {
if (++count == 1) { if (++count == 1) {
object.b = 2; object.b = 2;
} }
return !(isFind || isSome); return !(isFind || isSome);
}, isReduce ? object : null); }, isReduce ? object : null);
assert.strictEqual(count, 1); assert.strictEqual(count, 1);
} }
else { else {
skipTest(assert); skipAssert(assert);
} }
}); });
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('object assignments'); QUnit.module('object assignments');
lodashStable.each(['assign', 'assignIn', 'defaults', 'merge'], function(method Name) { lodashStable.each(['assign', 'assignIn', 'defaults', 'defaultsDeep', 'merge'], function(methodName) {
var func = _[methodName], var func = _[methodName],
isAssign = methodName == 'assign', isAssign = methodName == 'assign',
isDefaults = methodName == 'defaults'; isDefaults = /^defaults/.test(methodName);
QUnit.test('`_.' + methodName + '` should coerce primitives to objects', fun ction(assert) { QUnit.test('`_.' + methodName + '` should coerce primitives to objects', fun ction(assert) {
assert.expect(1); assert.expect(1);
var expected = lodashStable.map(falsey, alwaysTrue); var expected = lodashStable.map(primitives, function(value) {
var object = Object(value);
object.a = 1;
return object;
});
var actual = lodashStable.map(falsey, function(object, index) { var actual = lodashStable.map(primitives, function(value) {
var result = index ? func(object) : func(); return func(value, { 'a': 1 });
return lodashStable.isEqual(result, Object(object));
}); });
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
}); });
QUnit.test('`_.' + methodName + '` should assign own ' + (isAssign ? '' : 'a nd inherited ') + 'source properties', function(assert) { QUnit.test('`_.' + methodName + '` should assign own ' + (isAssign ? '' : 'a nd inherited ') + 'string keyed source properties', function(assert) {
assert.expect(1); assert.expect(1);
function Foo() { this.a = 1; } function Foo() {
this.a = 1;
}
Foo.prototype.b = 2; Foo.prototype.b = 2;
var expected = isAssign ? { 'a': 1 } : { 'a': 1, 'b': 2 }; var expected = isAssign ? { 'a': 1 } : { 'a': 1, 'b': 2 };
assert.deepEqual(func({}, new Foo), expected); assert.deepEqual(func({}, new Foo), expected);
}); });
QUnit.test('`_.' + methodName + '` should not skip a trailing function sourc
e', function(assert) {
assert.expect(1);
function fn() {}
fn.b = 2;
assert.deepEqual(func({}, { 'a': 1 }, fn), { 'a': 1, 'b': 2 });
});
QUnit.test('`_.' + methodName + '` should not error on nullish sources', fun ction(assert) { QUnit.test('`_.' + methodName + '` should not error on nullish sources', fun ction(assert) {
assert.expect(1); assert.expect(1);
try { try {
assert.deepEqual(func({ 'a': 1 }, undefined, { 'b': 2 }, null), { 'a': 1 , 'b': 2 }); assert.deepEqual(func({ 'a': 1 }, undefined, { 'b': 2 }, null), { 'a': 1 , 'b': 2 });
} catch (e) { } catch (e) {
assert.ok(false, e.message); assert.ok(false, e.message);
} }
}); });
QUnit.test('`_.' + methodName + '` should create an object when `object` is nullish', function(assert) { QUnit.test('`_.' + methodName + '` should create an object when `object` is nullish', function(assert) {
assert.expect(2); assert.expect(2);
var source = { 'a': 1 }, var source = { 'a': 1 },
values = [null, undefined], values = [null, undefined],
expected = lodashStable.map(values, alwaysTrue); expected = lodashStable.map(values, stubTrue);
var actual = lodashStable.map(values, function(value) { var actual = lodashStable.map(values, function(value) {
var object = func(value, source); var object = func(value, source);
return object !== source && lodashStable.isEqual(object, source); return object !== source && lodashStable.isEqual(object, source);
}); });
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
actual = lodashStable.map(values, function(value) { actual = lodashStable.map(values, function(value) {
return lodashStable.isEqual(func(value), {}); return lodashStable.isEqual(func(value), {});
skipping to change at line 6115 skipping to change at line 7337
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
}); });
QUnit.test('`_.' + methodName + '` should work as an iteratee for methods li ke `_.reduce`', function(assert) { QUnit.test('`_.' + methodName + '` should work as an iteratee for methods li ke `_.reduce`', function(assert) {
assert.expect(2); assert.expect(2);
var array = [{ 'a': 1 }, { 'b': 2 }, { 'c': 3 }], var array = [{ 'a': 1 }, { 'b': 2 }, { 'c': 3 }],
expected = { 'a': isDefaults ? 0 : 1, 'b': 2, 'c': 3 }; expected = { 'a': isDefaults ? 0 : 1, 'b': 2, 'c': 3 };
assert.deepEqual(lodashStable.reduce(array, func, { 'a': 0 }), expected); function fn() {};
var fn = function() {};
fn.a = array[0]; fn.a = array[0];
fn.b = array[1]; fn.b = array[1];
fn.c = array[2]; fn.c = array[2];
assert.deepEqual(_.reduce(fn, func, { 'a': 0 }), expected); assert.deepEqual(lodashStable.reduce(array, func, { 'a': 0 }), expected);
assert.deepEqual(lodashStable.reduce(fn, func, { 'a': 0 }), expected);
}); });
QUnit.test('`_.' + methodName + '` should not return the existing wrapped va lue when chaining', function(assert) { QUnit.test('`_.' + methodName + '` should not return the existing wrapped va lue when chaining', function(assert) {
assert.expect(1); assert.expect(1);
if (!isNpm) { if (!isNpm) {
var wrapped = _({ 'a': 1 }), var wrapped = _({ 'a': 1 }),
actual = wrapped[methodName]({ 'b': 2 }); actual = wrapped[methodName]({ 'b': 2 });
assert.notStrictEqual(actual, wrapped); assert.notStrictEqual(actual, wrapped);
} }
else { else {
skipTest(assert); skipAssert(assert);
} }
}); });
}); });
lodashStable.each(['assign', 'assignIn', 'merge'], function(methodName) { lodashStable.each(['assign', 'assignIn', 'merge'], function(methodName) {
var func = _[methodName]; var func = _[methodName];
QUnit.test('`_.' + methodName + '` should not treat `object` as `source`', f unction(assert) { QUnit.test('`_.' + methodName + '` should not treat `object` as `source`', f unction(assert) {
assert.expect(1); assert.expect(1);
function Foo() {} function Foo() {}
Foo.prototype.a = 1; Foo.prototype.a = 1;
var actual = func(new Foo, { 'b': 2 }); var actual = func(new Foo, { 'b': 2 });
assert.notOk(_.has(actual, 'a')); assert.notOk(_.has(actual, 'a'));
}); });
}); });
lodashStable.each(['assign', 'assignIn', 'assignInWith', 'assignWith', 'defaul ts', 'merge', 'mergeWith'], function(methodName) { lodashStable.each(['assign', 'assignIn', 'assignInWith', 'assignWith', 'defaul ts', 'defaultsDeep', 'merge', 'mergeWith'], function(methodName) {
var func = _[methodName]; var func = _[methodName];
QUnit.test('`_.' + methodName + '` should not assign values that are the sam e as their destinations', function(assert) { QUnit.test('`_.' + methodName + '` should not assign values that are the sam e as their destinations', function(assert) {
assert.expect(4); assert.expect(4);
lodashStable.each(['a', ['a'], { 'a': 1 }, NaN], function(value) { lodashStable.each(['a', ['a'], { 'a': 1 }, NaN], function(value) {
if (defineProperty) { var object = {},
var object = {}, pass = true;
pass = true;
defineProperty(object, 'a', { defineProperty(object, 'a', {
'enumerable': true, 'configurable': true,
'configurable': true, 'enumerable': true,
'get': lodashStable.constant(value), 'get': lodashStable.constant(value),
'set': function() { pass = false; } 'set': function() { pass = false; }
}); });
func(object, { 'a': value }); func(object, { 'a': value });
assert.ok(pass); assert.ok(pass);
}
else {
skipTest(assert);
}
}); });
}); });
}); });
lodashStable.each(['assignWith', 'assignInWith', 'mergeWith'], function(method Name) { lodashStable.each(['assignWith', 'assignInWith', 'mergeWith'], function(method Name) {
var func = _[methodName], var func = _[methodName],
isMergeWith = methodName == 'mergeWith'; isMergeWith = methodName == 'mergeWith';
QUnit.test('`_.' + methodName + '` should provide the correct `customizer` a rguments', function(assert) { QUnit.test('`_.' + methodName + '` should provide correct `customizer` argum ents', function(assert) {
assert.expect(3); assert.expect(3);
var args, var args,
object = { 'a': 1 }, object = { 'a': 1 },
source = { 'a': 2 }, source = { 'a': 2 },
expected = lodashStable.map([1, 2, 'a', object, source], lodashStable. cloneDeep); expected = lodashStable.map([1, 2, 'a', object, source], lodashStable. cloneDeep);
func(object, source, function() { func(object, source, function() {
args || (args = lodashStable.map(slice.call(arguments, 0, 5), lodashStab le.cloneDeep)); args || (args = lodashStable.map(slice.call(arguments, 0, 5), lodashStab le.cloneDeep));
}); });
assert.deepEqual(args, expected, 'primitive property values'); assert.deepEqual(args, expected, 'primitive values');
args = undefined;
object = { 'a': 1 };
source = { 'b': 2 };
expected = lodashStable.map([undefined, 2, 'b', object, source], lodashSta
ble.cloneDeep);
func(object, source, function() {
args || (args = lodashStable.map(slice.call(arguments, 0, 5), lodashStab
le.cloneDeep));
});
assert.deepEqual(args, expected, 'missing destination property');
var argsList = [], var argsList = [],
objectValue = [1, 2], objectValue = [1, 2],
sourceValue = { 'b': 2 }; sourceValue = { 'b': 2 };
object = { 'a': objectValue }; object = { 'a': objectValue };
source = { 'a': sourceValue }; source = { 'a': sourceValue };
expected = [lodashStable.map([objectValue, sourceValue, 'a', object, sourc e], lodashStable.cloneDeep)]; expected = [lodashStable.map([objectValue, sourceValue, 'a', object, sourc e], lodashStable.cloneDeep)];
if (isMergeWith) { if (isMergeWith) {
expected.push(lodashStable.map([undefined, 2, 'b', objectValue, sourceVa lue], lodashStable.cloneDeep)); expected.push(lodashStable.map([undefined, 2, 'b', objectValue, sourceVa lue], lodashStable.cloneDeep));
} }
func(object, source, function() { func(object, source, function() {
argsList.push(lodashStable.map(slice.call(arguments, 0, 5), lodashStable .cloneDeep)); argsList.push(lodashStable.map(slice.call(arguments, 0, 5), lodashStable .cloneDeep));
}); });
assert.deepEqual(argsList, expected, 'object property values'); assert.deepEqual(argsList, expected, 'object values');
args = undefined;
object = { 'a': 1 };
source = { 'b': 2 };
expected = lodashStable.map([undefined, 2, 'b', object, source], lodashSta
ble.cloneDeep);
func(object, source, function() {
args || (args = lodashStable.map(slice.call(arguments, 0, 5), lodashStab
le.cloneDeep));
});
assert.deepEqual(args, expected, 'undefined properties');
}); });
QUnit.test('`_.' + methodName + '` should not treat the second argument as a `customizer` callback', function(assert) { QUnit.test('`_.' + methodName + '` should not treat the second argument as a `customizer` callback', function(assert) {
assert.expect(2); assert.expect(2);
function callback() {} function callback() {}
callback.b = 2; callback.b = 2;
var actual = func({ 'a': 1 }, callback); var actual = func({ 'a': 1 }, callback);
assert.deepEqual(actual, { 'a': 1, 'b': 2 }); assert.deepEqual(actual, { 'a': 1, 'b': 2 });
skipping to change at line 6265 skipping to change at line 7481
values = []; values = [];
func(array, function(value, other) { func(array, function(value, other) {
values.push(lodashStable.isArray(value) ? other : value); values.push(lodashStable.isArray(value) ? other : value);
return false; return false;
}); });
assert.deepEqual(values, [lodashStable.endsWith(methodName, 'Right') ? 3 : 1]); assert.deepEqual(values, [lodashStable.endsWith(methodName, 'Right') ? 3 : 1]);
} }
else { else {
skipTest(assert); skipAssert(assert);
} }
}); });
QUnit.test('`_.' + methodName + '` can exit early when iterating objects', f unction(assert) { QUnit.test('`_.' + methodName + '` can exit early when iterating objects', f unction(assert) {
assert.expect(1); assert.expect(1);
if (func) { if (func) {
var object = { 'a': 1, 'b': 2, 'c': 3 }, var object = { 'a': 1, 'b': 2, 'c': 3 },
values = []; values = [];
func(object, function(value, other) { func(object, function(value, other) {
values.push(lodashStable.isArray(value) ? other : value); values.push(lodashStable.isArray(value) ? other : value);
return false; return false;
}); });
assert.strictEqual(values.length, 1); assert.strictEqual(values.length, 1);
} }
else { else {
skipTest(assert); skipAssert(assert);
} }
}); });
}); });
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('`__proto__` property bugs'); QUnit.module('`__proto__` property bugs');
(function() { (function() {
QUnit.test('internal data objects should work with the `__proto__` key', fun ction(assert) { QUnit.test('should work with the "__proto__" key in internal data objects', function(assert) {
assert.expect(4); assert.expect(4);
var stringLiteral = '__proto__', var stringLiteral = '__proto__',
stringObject = Object(stringLiteral), stringObject = Object(stringLiteral),
expected = [stringLiteral, stringObject]; expected = [stringLiteral, stringObject];
var largeArray = lodashStable.times(LARGE_ARRAY_SIZE, function(count) { var largeArray = lodashStable.times(LARGE_ARRAY_SIZE, function(count) {
return isEven(count) ? stringLiteral : stringObject; return isEven(count) ? stringLiteral : stringObject;
}); });
assert.deepEqual(_.difference(largeArray, largeArray), []); assert.deepEqual(_.difference(largeArray, largeArray), []);
assert.deepEqual(_.intersection(largeArray, largeArray), expected); assert.deepEqual(_.intersection(largeArray, largeArray), expected);
assert.deepEqual(_.uniq(largeArray), expected); assert.deepEqual(_.uniq(largeArray), expected);
assert.deepEqual(_.without.apply(_, [largeArray].concat(largeArray)), []); assert.deepEqual(_.without.apply(_, [largeArray].concat(largeArray)), []);
}); });
QUnit.test('should treat "__proto__" as a regular key in assignments', funct
ion(assert) {
assert.expect(2);
var methods = [
'assign',
'assignIn',
'defaults',
'defaultsDeep',
'merge'
];
var source = create(null);
source.__proto__ = [];
var expected = lodashStable.map(methods, stubFalse);
var actual = lodashStable.map(methods, function(methodName) {
var result = _[methodName]({}, source);
return result instanceof Array;
});
assert.deepEqual(actual, expected);
actual = _.groupBy([{ 'a': '__proto__' }], 'a');
assert.notOk(actual instanceof Array);
});
QUnit.test('should not merge "__proto__" properties', function(assert) {
assert.expect(1);
if (JSON) {
_.merge({}, JSON.parse('{"__proto__":{"a":1}}'));
var actual = 'a' in objectProto;
delete objectProto.a;
assert.notOk(actual);
} else {
skipAssert(assert);
}
});
QUnit.test('should not indirectly merge builtin prototype properties', funct
ion(assert) {
assert.expect(2);
_.merge({}, { 'toString': { 'constructor': { 'prototype': { 'a': 1 } } } }
);
var actual = 'a' in funcProto;
delete funcProto.a;
assert.notOk(actual);
_.merge({}, { 'constructor': { 'prototype': { 'a': 1 } } });
actual = 'a' in objectProto;
delete objectProto.a;
assert.notOk(actual);
});
QUnit.test('should not indirectly merge `Object` properties', function(asser
t) {
assert.expect(1);
_.merge({}, { 'constructor': { 'a': 1 } });
var actual = 'a' in Object;
delete Object.a;
assert.notOk(actual);
});
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.fromPairs'); QUnit.module('lodash.fromPairs');
(function() { (function() {
var object = { 'barney': 36, 'fred': 40 },
array = [['barney', 36], ['fred', 40]];
QUnit.test('should accept a two dimensional array', function(assert) { QUnit.test('should accept a two dimensional array', function(assert) {
assert.expect(1); assert.expect(1);
var actual = _.fromPairs(array); var array = [['a', 1], ['b', 2]],
object = { 'a': 1, 'b': 2 },
actual = _.fromPairs(array);
assert.deepEqual(actual, object); assert.deepEqual(actual, object);
}); });
QUnit.test('should accept a falsey `array` argument', function(assert) { QUnit.test('should accept a falsey `array`', function(assert) {
assert.expect(1); assert.expect(1);
var expected = lodashStable.map(falsey, alwaysEmptyObject); var expected = lodashStable.map(falsey, stubObject);
var actual = lodashStable.map(falsey, function(array, index) { var actual = lodashStable.map(falsey, function(array, index) {
try { try {
return index ? _.fromPairs(array) : _.fromPairs(); return index ? _.fromPairs(array) : _.fromPairs();
} catch (e) {} } catch (e) {}
}); });
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
}); });
QUnit.test('should support deep paths', function(assert) { QUnit.test('should not support deep paths', function(assert) {
assert.expect(1); assert.expect(1);
var actual = _.fromPairs([['a.b.c', 1]]); var actual = _.fromPairs([['a.b', 1]]);
assert.deepEqual(actual, { 'a': { 'b': { 'c': 1 } } }); assert.deepEqual(actual, { 'a.b': 1 });
}); });
QUnit.test('should support consuming the return value of `_.toPairs`', funct ion(assert) { QUnit.test('should support consuming the return value of `_.toPairs`', funct ion(assert) {
assert.expect(1); assert.expect(1);
var object = { 'a.b': 1 };
assert.deepEqual(_.fromPairs(_.toPairs(object)), object); assert.deepEqual(_.fromPairs(_.toPairs(object)), object);
}); });
QUnit.test('should work in a lazy sequence', function(assert) { QUnit.test('should work in a lazy sequence', function(assert) {
assert.expect(1); assert.expect(1);
if (!isNpm) { if (!isNpm) {
var array = lodashStable.times(LARGE_ARRAY_SIZE, function(index) { var array = lodashStable.times(LARGE_ARRAY_SIZE, function(index) {
return ['key' + index, index]; return ['key' + index, index];
}); });
var actual = _(array).fromPairs().map(square).filter(isEven).take().valu e(); var actual = _(array).fromPairs().map(square).filter(isEven).take().valu e();
assert.deepEqual(actual, _.take(_.filter(_.map(_.fromPairs(array), squar e), isEven))); assert.deepEqual(actual, _.take(_.filter(_.map(_.fromPairs(array), squar e), isEven)));
} }
else { else {
skipTest(assert); skipAssert(assert);
} }
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.functions'); QUnit.module('lodash.functions');
(function() { (function() {
QUnit.test('should return the function names of an object', function(assert) { QUnit.test('should return the function names of an object', function(assert) {
assert.expect(1); assert.expect(1);
var object = { 'a': 'a', 'b': identity, 'c': /x/, 'd': lodashStable.each } var object = { 'a': 'a', 'b': identity, 'c': /x/, 'd': noop },
; actual = _.functions(object).sort();
assert.deepEqual(_.functions(object).sort(), ['b', 'd']);
assert.deepEqual(actual, ['b', 'd']);
}); });
QUnit.test('should not include inherited functions', function(assert) { QUnit.test('should not include inherited functions', function(assert) {
assert.expect(1); assert.expect(1);
function Foo() { function Foo() {
this.a = identity; this.a = identity;
this.b = 'b'; this.b = 'b';
} }
Foo.prototype.c = noop; Foo.prototype.c = noop;
assert.deepEqual(_.functions(new Foo).sort(), ['a']);
assert.deepEqual(_.functions(new Foo), ['a']);
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.groupBy'); QUnit.module('lodash.groupBy');
(function() { (function() {
var array = [4.2, 6.1, 6.4]; var array = [6.1, 4.2, 6.3];
QUnit.test('should transform keys by `iteratee`', function(assert) {
assert.expect(1);
var actual = _.groupBy(array, Math.floor);
assert.deepEqual(actual, { '4': [4.2], '6': [6.1, 6.3] });
});
QUnit.test('should use `_.identity` when `iteratee` is nullish', function(as sert) { QUnit.test('should use `_.identity` when `iteratee` is nullish', function(as sert) {
assert.expect(1); assert.expect(1);
var array = [4, 6, 6], var array = [6, 4, 6],
values = [, null, undefined], values = [, null, undefined],
expected = lodashStable.map(values, lodashStable.constant({ '4': [4], '6': [6, 6] })); expected = lodashStable.map(values, lodashStable.constant({ '4': [4], '6': [6, 6] }));
var actual = lodashStable.map(values, function(value, index) { var actual = lodashStable.map(values, function(value, index) {
return index ? _.groupBy(array, value) : _.groupBy(array); return index ? _.groupBy(array, value) : _.groupBy(array);
}); });
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
}); });
QUnit.test('should work with a "_.property" style `iteratee`', function(asse rt) { QUnit.test('should work with `_.property` shorthands', function(assert) {
assert.expect(1); assert.expect(1);
var actual = _.groupBy(['one', 'two', 'three'], 'length'); var actual = _.groupBy(['one', 'two', 'three'], 'length');
assert.deepEqual(actual, { '3': ['one', 'two'], '5': ['three'] }); assert.deepEqual(actual, { '3': ['one', 'two'], '5': ['three'] });
}); });
QUnit.test('should only add values to own, not inherited, properties', funct ion(assert) { QUnit.test('should only add values to own, not inherited, properties', funct ion(assert) {
assert.expect(2); assert.expect(2);
var actual = _.groupBy([4.2, 6.1, 6.4], function(num) { var actual = _.groupBy(array, function(n) {
return Math.floor(num) > 4 ? 'hasOwnProperty' : 'constructor'; return Math.floor(n) > 4 ? 'hasOwnProperty' : 'constructor';
}); });
assert.deepEqual(actual.constructor, [4.2]); assert.deepEqual(actual.constructor, [4.2]);
assert.deepEqual(actual.hasOwnProperty, [6.1, 6.4]); assert.deepEqual(actual.hasOwnProperty, [6.1, 6.3]);
}); });
QUnit.test('should work with a number for `iteratee`', function(assert) { QUnit.test('should work with a number for `iteratee`', function(assert) {
assert.expect(2); assert.expect(2);
var array = [ var array = [
[1, 'a'], [1, 'a'],
[2, 'a'], [2, 'a'],
[2, 'b'] [2, 'b']
]; ];
assert.deepEqual(_.groupBy(array, 0), { '1': [[1, 'a']], '2': [[2, 'a'], [ 2, 'b']] }); assert.deepEqual(_.groupBy(array, 0), { '1': [[1, 'a']], '2': [[2, 'a'], [ 2, 'b']] });
assert.deepEqual(_.groupBy(array, 1), { 'a': [[1, 'a'], [2, 'a']], 'b': [[ 2, 'b']] }); assert.deepEqual(_.groupBy(array, 1), { 'a': [[1, 'a'], [2, 'a']], 'b': [[ 2, 'b']] });
}); });
QUnit.test('should work with an object for `collection`', function(assert) { QUnit.test('should work with an object for `collection`', function(assert) {
assert.expect(1); assert.expect(1);
var actual = _.groupBy({ 'a': 4.2, 'b': 6.1, 'c': 6.4 }, function(num) { var actual = _.groupBy({ 'a': 6.1, 'b': 4.2, 'c': 6.3 }, Math.floor);
return Math.floor(num); assert.deepEqual(actual, { '4': [4.2], '6': [6.1, 6.3] });
});
assert.deepEqual(actual, { '4': [4.2], '6': [6.1, 6.4] });
}); });
QUnit.test('should work in a lazy sequence', function(assert) { QUnit.test('should work in a lazy sequence', function(assert) {
assert.expect(1); assert.expect(1);
if (!isNpm) { if (!isNpm) {
var array = lodashStable.range(LARGE_ARRAY_SIZE).concat( var array = lodashStable.range(LARGE_ARRAY_SIZE).concat(
lodashStable.range(Math.floor(LARGE_ARRAY_SIZE / 2), LARGE_ARRAY_SIZE) , lodashStable.range(Math.floor(LARGE_ARRAY_SIZE / 2), LARGE_ARRAY_SIZE) ,
lodashStable.range(Math.floor(LARGE_ARRAY_SIZE / 1.5), LARGE_ARRAY_SIZ E) lodashStable.range(Math.floor(LARGE_ARRAY_SIZE / 1.5), LARGE_ARRAY_SIZ E)
); );
var iteratee = function(value) { value.push(value[0]); return value; }, var iteratee = function(value) { value.push(value[0]); return value; },
predicate = function(value) { return isEven(value[0]); }, predicate = function(value) { return isEven(value[0]); },
actual = _(array).groupBy().map(iteratee).filter(predicate).take().v alue(); actual = _(array).groupBy().map(iteratee).filter(predicate).take().v alue();
assert.deepEqual(actual, _.take(_.filter(lodashStable.map(_.groupBy(arra y), iteratee), predicate))); assert.deepEqual(actual, _.take(_.filter(lodashStable.map(_.groupBy(arra y), iteratee), predicate)));
} }
else { else {
skipTest(assert); skipAssert(assert);
} }
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.gt'); QUnit.module('lodash.gt');
(function() { (function() {
QUnit.test('should return `true` if `value` > `other`', function(assert) { QUnit.test('should return `true` if `value` > `other`', function(assert) {
assert.expect(2); assert.expect(2);
assert.strictEqual(_.gt(3, 1), true); assert.strictEqual(_.gt(3, 1), true);
assert.strictEqual(_.gt('def', 'abc'), true); assert.strictEqual(_.gt('def', 'abc'), true);
}); });
QUnit.test('should return `false` if `value` is less than or equal to `other `', function(assert) { QUnit.test('should return `false` if `value` is <= `other`', function(assert ) {
assert.expect(4); assert.expect(4);
assert.strictEqual(_.gt(1, 3), false); assert.strictEqual(_.gt(1, 3), false);
assert.strictEqual(_.gt(3, 3), false); assert.strictEqual(_.gt(3, 3), false);
assert.strictEqual(_.gt('abc', 'def'), false); assert.strictEqual(_.gt('abc', 'def'), false);
assert.strictEqual(_.gt('def', 'def'), false); assert.strictEqual(_.gt('def', 'def'), false);
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
skipping to change at line 6528 skipping to change at line 7823
assert.strictEqual(_.gte(1, 3), false); assert.strictEqual(_.gte(1, 3), false);
assert.strictEqual(_.gte('abc', 'def'), false); assert.strictEqual(_.gte('abc', 'def'), false);
}); });
}()); }());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('has methods'); QUnit.module('has methods');
lodashStable.each(['has', 'hasIn'], function(methodName) { lodashStable.each(['has', 'hasIn'], function(methodName) {
var args = (function() { return arguments; }(1, 2, 3)), var func = _[methodName],
func = _[methodName], isHas = methodName == 'has',
isHas = methodName == 'has'; sparseArgs = toArgs([1]),
sparseArray = Array(1),
sparseString = Object('a');
delete sparseArgs[0];
delete sparseString[0];
QUnit.test('`_.' + methodName + '` should check for own properties', functio n(assert) { QUnit.test('`_.' + methodName + '` should check for own properties', functio n(assert) {
assert.expect(2); assert.expect(2);
var object = { 'a': 1 }; var object = { 'a': 1 };
lodashStable.each(['a', ['a']], function(path) { lodashStable.each(['a', ['a']], function(path) {
assert.strictEqual(func(object, path), true); assert.strictEqual(func(object, path), true);
}); });
}); });
QUnit.test('`_.' + methodName + '` should not use the `hasOwnProperty` metho d of the object', function(assert) { QUnit.test('`_.' + methodName + '` should not use the `hasOwnProperty` metho d of `object`', function(assert) {
assert.expect(1); assert.expect(1);
var object = { 'hasOwnProperty': null, 'a': 1 }; var object = { 'hasOwnProperty': null, 'a': 1 };
assert.strictEqual(func(object, 'a'), true); assert.strictEqual(func(object, 'a'), true);
}); });
QUnit.test('`_.' + methodName + '` should support deep paths', function(asse rt) { QUnit.test('`_.' + methodName + '` should support deep paths', function(asse rt) {
assert.expect(2); assert.expect(4);
var object = { 'a': { 'b': { 'c': 3 } } }; var object = { 'a': { 'b': 2 } };
lodashStable.each(['a.b.c', ['a', 'b', 'c']], function(path) { lodashStable.each(['a.b', ['a', 'b']], function(path) {
assert.strictEqual(func(object, path), true); assert.strictEqual(func(object, path), true);
}); });
lodashStable.each(['a.a', ['a', 'a']], function(path) {
assert.strictEqual(func(object, path), false);
});
}); });
QUnit.test('`_.' + methodName + '` should coerce `path` to a string', functi on(assert) { QUnit.test('`_.' + methodName + '` should coerce `path` to a string', functi on(assert) {
assert.expect(1); assert.expect(2);
function fn() {} function fn() {}
fn.toString = lodashStable.constant('fn'); fn.toString = lodashStable.constant('fn');
var expected = [1, 1, 2, 2, 3, 3, 4, 4], var object = { 'null': 1 , 'undefined': 2, 'fn': 3, '[object Object]': 4 }
objects = [{ 'null': 1 }, { 'undefined': 2 }, { 'fn': 3 }, { '[object ,
Object]': 4 }], paths = [null, undefined, fn, {}],
values = [null, undefined, fn, {}]; expected = lodashStable.map(paths, stubTrue);
var actual = lodashStable.transform(objects, function(result, object, inde lodashStable.times(2, function(index) {
x) { var actual = lodashStable.map(paths, function(path) {
var key = values[index]; return func(object, index ? [path] : path);
lodashStable.each([key, [key]], function(path) {
var prop = _.property(key);
result.push(prop(object));
}); });
});
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
});
}); });
QUnit.test('`_.' + methodName + '` should work with `arguments` objects', fu nction(assert) { QUnit.test('`_.' + methodName + '` should work with `arguments` objects', fu nction(assert) {
assert.expect(1); assert.expect(1);
assert.strictEqual(func(args, 1), true); assert.strictEqual(func(args, 1), true);
}); });
QUnit.test('`_.' + methodName + '` should work with non-string `path` argume nts', function(assert) { QUnit.test('`_.' + methodName + '` should work with a non-string `path`', fu nction(assert) {
assert.expect(2); assert.expect(2);
var array = [1, 2, 3]; var array = [1, 2, 3];
lodashStable.each([1, [1]], function(path) { lodashStable.each([1, [1]], function(path) {
assert.strictEqual(func(array, path), true); assert.strictEqual(func(array, path), true);
}); });
}); });
QUnit.test('`_.' + methodName + '` should work for objects with a `[[Prototy pe]]` of `null`', function(assert) { QUnit.test('`_.' + methodName + '` should preserve the sign of `0`', functio n(assert) {
assert.expect(1); assert.expect(1);
if (create) { var object = { '-0': 'a', '0': 'b' },
var object = create(null); props = [-0, Object(-0), 0, Object(0)],
object[1] = 'a'; expected = lodashStable.map(props, stubTrue);
assert.strictEqual(func(object, 1), true);
var actual = lodashStable.map(props, function(key) {
return func(object, key);
});
assert.deepEqual(actual, expected);
});
QUnit.test('`_.' + methodName + '` should work with a symbol `path`', functi
on(assert) {
assert.expect(2);
function Foo() {}
if (Symbol) {
Foo.prototype[symbol] = 1;
var symbol2 = Symbol('b');
defineProperty(Foo.prototype, symbol2, {
'configurable': true,
'enumerable': false,
'writable': true,
'value': 2
});
var object = isHas ? Foo.prototype : new Foo;
assert.strictEqual(func(object, symbol), true);
assert.strictEqual(func(object, symbol2), true);
} }
else { else {
skipTest(assert); skipAssert(assert, 2);
} }
}); });
QUnit.test('`_.' + methodName + '` should check for a key over a path', func tion(assert) { QUnit.test('`_.' + methodName + '` should check for a key over a path', func tion(assert) {
assert.expect(2); assert.expect(2);
var object = { 'a.b.c': 3, 'a': { 'b': { 'c': 4 } } }; var object = { 'a.b': 1 };
lodashStable.each(['a.b.c', ['a.b.c']], function(path) { lodashStable.each(['a.b', ['a.b']], function(path) {
assert.strictEqual(func(object, path), true); assert.strictEqual(func(object, path), true);
}); });
}); });
QUnit.test('`_.' + methodName + '` should return `true` for indexes of spars
e values', function(assert) {
assert.expect(1);
var values = [sparseArgs, sparseArray, sparseString],
expected = lodashStable.map(values, stubTrue);
var actual = lodashStable.map(values, function(value) {
return func(value, 0);
});
assert.deepEqual(actual, expected);
});
QUnit.test('`_.' + methodName + '` should return `true` for indexes of spars
e values with deep paths', function(assert) {
assert.expect(1);
var values = [sparseArgs, sparseArray, sparseString],
expected = lodashStable.map(values, lodashStable.constant([true, true]
));
var actual = lodashStable.map(values, function(value) {
return lodashStable.map(['a[0]', ['a', '0']], function(path) {
return func({ 'a': value }, path);
});
});
assert.deepEqual(actual, expected);
});
QUnit.test('`_.' + methodName + '` should return `' + (isHas ? 'false' : 'tr ue') + '` for inherited properties', function(assert) { QUnit.test('`_.' + methodName + '` should return `' + (isHas ? 'false' : 'tr ue') + '` for inherited properties', function(assert) {
assert.expect(2); assert.expect(2);
function Foo() {} function Foo() {}
Foo.prototype.a = 1; Foo.prototype.a = 1;
lodashStable.each(['a', ['a']], function(path) { lodashStable.each(['a', ['a']], function(path) {
assert.strictEqual(func(new Foo, path), !isHas); assert.strictEqual(func(new Foo, path), !isHas);
}); });
}); });
QUnit.test('`_.' + methodName + '` should return `true` for index values wit QUnit.test('`_.' + methodName + '` should return `' + (isHas ? 'false' : 'tr
hin bounds for arrays, `arguments` objects, and strings', function(assert) { ue') + '` for nested inherited properties', function(assert) {
assert.expect(1); assert.expect(2);
var string = Object('abc');
delete args[0];
delete string[0];
var values = [Array(3), args, string], function Foo() {}
expected = lodashStable.map(values, alwaysTrue); Foo.prototype.a = { 'b': 1 };
var actual = lodashStable.map(values, function(value) { lodashStable.each(['a.b', ['a', 'b']], function(path) {
return func(value, 0); assert.strictEqual(func(new Foo, path), !isHas);
}); });
assert.deepEqual(actual, expected);
args[0] = 1;
}); });
QUnit.test('`_.' + methodName + '` should return `false` when `object` is nu llish', function(assert) { QUnit.test('`_.' + methodName + '` should return `false` when `object` is nu llish', function(assert) {
assert.expect(2); assert.expect(2);
var values = [null, undefined], var values = [null, undefined],
expected = lodashStable.map(values, alwaysFalse); expected = lodashStable.map(values, stubFalse);
lodashStable.each(['constructor', ['constructor']], function(path) { lodashStable.each(['constructor', ['constructor']], function(path) {
var actual = lodashStable.map(values, function(value) { var actual = lodashStable.map(values, function(value) {
return func(value, path); return func(value, path);
}); });
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
}); });
}); });
QUnit.test('`_.' + methodName + '` should return `false` with deep paths whe n `object` is nullish', function(assert) { QUnit.test('`_.' + methodName + '` should return `false` for deep paths when `object` is nullish', function(assert) {
assert.expect(2); assert.expect(2);
var values = [null, undefined], var values = [null, undefined],