1;(function() { 2 3 /** Used as a safe reference for `undefined` in pre-ES5 environments. */ 4 var undefined; 5 6 /** Used to detect when a function becomes hot. */ 7 var HOT_COUNT = 150; 8 9 /** Used as the size to cover large array optimizations. */ 10 var LARGE_ARRAY_SIZE = 200; 11 12 /** Used as the `TypeError` message for "Functions" methods. */ 13 var FUNC_ERROR_TEXT = 'Expected a function'; 14 15 /** Used as the maximum memoize cache size. */ 16 var MAX_MEMOIZE_SIZE = 500; 17 18 /** Used as references for various `Number` constants. */ 19 var MAX_SAFE_INTEGER = 9007199254740991, 20 MAX_INTEGER = 1.7976931348623157e+308; 21 22 /** Used as references for the maximum length and index of an array. */ 23 var MAX_ARRAY_LENGTH = 4294967295, 24 MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1; 25 26 /** `Object#toString` result references. */ 27 var funcTag = '[object Function]', 28 numberTag = '[object Number]', 29 objectTag = '[object Object]'; 30 31 /** Used as a reference to the global object. */ 32 var root = (typeof global == 'object' && global) || this; 33 34 /** Used to store lodash to test for bad extensions/shims. */ 35 var lodashBizarro = root.lodashBizarro; 36 37 /** Used for native method references. */ 38 var arrayProto = Array.prototype, 39 funcProto = Function.prototype, 40 objectProto = Object.prototype, 41 numberProto = Number.prototype, 42 stringProto = String.prototype; 43 44 /** Method and object shortcuts. */ 45 var phantom = root.phantom, 46 process = root.process, 47 amd = root.define ? define.amd : undefined, 48 args = toArgs([1, 2, 3]), 49 argv = process ? process.argv : undefined, 50 defineProperty = Object.defineProperty, 51 document = phantom ? undefined : root.document, 52 body = root.document ? root.document.body : undefined, 53 create = Object.create, 54 fnToString = funcProto.toString, 55 freeze = Object.freeze, 56 getSymbols = Object.getOwnPropertySymbols, 57 identity = function(value) { return value; }, 58 noop = function() {}, 59 objToString = objectProto.toString, 60 params = argv, 61 push = arrayProto.push, 62 realm = {}, 63 slice = arrayProto.slice, 64 strictArgs = (function() { 'use strict'; return arguments; }(1, 2, 3)); 65 66 var ArrayBuffer = root.ArrayBuffer, 67 Buffer = root.Buffer, 68 Map = root.Map, 69 Promise = root.Promise, 70 Proxy = root.Proxy, 71 Set = root.Set, 72 Symbol = root.Symbol, 73 Uint8Array = root.Uint8Array, 74 WeakMap = root.WeakMap, 75 WeakSet = root.WeakSet; 76 77 var arrayBuffer = ArrayBuffer ? new ArrayBuffer(2) : undefined, 78 map = Map ? new Map : undefined, 79 promise = Promise ? Promise.resolve(1) : undefined, 80 set = Set ? new Set : undefined, 81 symbol = Symbol ? Symbol('a') : undefined, 82 weakMap = WeakMap ? new WeakMap : undefined, 83 weakSet = WeakSet ? new WeakSet : undefined; 84 85 /** Math helpers. */ 86 var add = function(x, y) { return x + y; }, 87 doubled = function(n) { return n * 2; }, 88 isEven = function(n) { return n % 2 == 0; }, 89 square = function(n) { return n * n; }; 90 91 /** Stub functions. */ 92 var stubA = function() { return 'a'; }, 93 stubB = function() { return 'b'; }, 94 stubC = function() { return 'c'; }; 95 96 var stubTrue = function() { return true; }, 97 stubFalse = function() { return false; }; 98 99 var stubNaN = function() { return NaN; }, 100 stubNull = function() { return null; }; 101 102 var stubZero = function() { return 0; }, 103 stubOne = function() { return 1; }, 104 stubTwo = function() { return 2; }, 105 stubThree = function() { return 3; }, 106 stubFour = function() { return 4; }; 107 108 var stubArray = function() { return []; }, 109 stubObject = function() { return {}; }, 110 stubString = function() { return ''; }; 111 112 /** List of Latin Unicode letters. */ 113 var burredLetters = [ 114 // Latin-1 Supplement letters. 115 '\xc0', '\xc1', '\xc2', '\xc3', '\xc4', '\xc5', '\xc6', '\xc7', '\xc8', '\xc9', '\xca', '\xcb', '\xcc', '\xcd', '\xce', '\xcf', 116 '\xd0', '\xd1', '\xd2', '\xd3', '\xd4', '\xd5', '\xd6', '\xd8', '\xd9', '\xda', '\xdb', '\xdc', '\xdd', '\xde', '\xdf', 117 '\xe0', '\xe1', '\xe2', '\xe3', '\xe4', '\xe5', '\xe6', '\xe7', '\xe8', '\xe9', '\xea', '\xeb', '\xec', '\xed', '\xee', '\xef', 118 '\xf0', '\xf1', '\xf2', '\xf3', '\xf4', '\xf5', '\xf6', '\xf8', '\xf9', '\xfa', '\xfb', '\xfc', '\xfd', '\xfe', '\xff', 119 // Latin Extended-A letters. 120 '\u0100', '\u0101', '\u0102', '\u0103', '\u0104', '\u0105', '\u0106', '\u0107', '\u0108', '\u0109', '\u010a', '\u010b', '\u010c', '\u010d', '\u010e', '\u010f', 121 '\u0110', '\u0111', '\u0112', '\u0113', '\u0114', '\u0115', '\u0116', '\u0117', '\u0118', '\u0119', '\u011a', '\u011b', '\u011c', '\u011d', '\u011e', '\u011f', 122 '\u0120', '\u0121', '\u0122', '\u0123', '\u0124', '\u0125', '\u0126', '\u0127', '\u0128', '\u0129', '\u012a', '\u012b', '\u012c', '\u012d', '\u012e', '\u012f', 123 '\u0130', '\u0131', '\u0132', '\u0133', '\u0134', '\u0135', '\u0136', '\u0137', '\u0138', '\u0139', '\u013a', '\u013b', '\u013c', '\u013d', '\u013e', '\u013f', 124 '\u0140', '\u0141', '\u0142', '\u0143', '\u0144', '\u0145', '\u0146', '\u0147', '\u0148', '\u0149', '\u014a', '\u014b', '\u014c', '\u014d', '\u014e', '\u014f', 125 '\u0150', '\u0151', '\u0152', '\u0153', '\u0154', '\u0155', '\u0156', '\u0157', '\u0158', '\u0159', '\u015a', '\u015b', '\u015c', '\u015d', '\u015e', '\u015f', 126 '\u0160', '\u0161', '\u0162', '\u0163', '\u0164', '\u0165', '\u0166', '\u0167', '\u0168', '\u0169', '\u016a', '\u016b', '\u016c', '\u016d', '\u016e', '\u016f', 127 '\u0170', '\u0171', '\u0172', '\u0173', '\u0174', '\u0175', '\u0176', '\u0177', '\u0178', '\u0179', '\u017a', '\u017b', '\u017c', '\u017d', '\u017e', '\u017f' 128 ]; 129 130 /** List of combining diacritical marks. */ 131 var comboMarks = [ 132 '\u0300', '\u0301', '\u0302', '\u0303', '\u0304', '\u0305', '\u0306', '\u0307', '\u0308', '\u0309', '\u030a', '\u030b', '\u030c', '\u030d', '\u030e', '\u030f', 133 '\u0310', '\u0311', '\u0312', '\u0313', '\u0314', '\u0315', '\u0316', '\u0317', '\u0318', '\u0319', '\u031a', '\u031b', '\u031c', '\u031d', '\u031e', '\u031f', 134 '\u0320', '\u0321', '\u0322', '\u0323', '\u0324', '\u0325', '\u0326', '\u0327', '\u0328', '\u0329', '\u032a', '\u032b', '\u032c', '\u032d', '\u032e', '\u032f', 135 '\u0330', '\u0331', '\u0332', '\u0333', '\u0334', '\u0335', '\u0336', '\u0337', '\u0338', '\u0339', '\u033a', '\u033b', '\u033c', '\u033d', '\u033e', '\u033f', 136 '\u0340', '\u0341', '\u0342', '\u0343', '\u0344', '\u0345', '\u0346', '\u0347', '\u0348', '\u0349', '\u034a', '\u034b', '\u034c', '\u034d', '\u034e', '\u034f', 137 '\u0350', '\u0351', '\u0352', '\u0353', '\u0354', '\u0355', '\u0356', '\u0357', '\u0358', '\u0359', '\u035a', '\u035b', '\u035c', '\u035d', '\u035e', '\u035f', 138 '\u0360', '\u0361', '\u0362', '\u0363', '\u0364', '\u0365', '\u0366', '\u0367', '\u0368', '\u0369', '\u036a', '\u036b', '\u036c', '\u036d', '\u036e', '\u036f', 139 '\ufe20', '\ufe21', '\ufe22', '\ufe23' 140 ]; 141 142 /** List of converted Latin Unicode letters. */ 143 var deburredLetters = [ 144 // Converted Latin-1 Supplement letters. 145 'A', 'A', 'A', 'A', 'A', 'A', 'Ae', 'C', 'E', 'E', 'E', 'E', 'I', 'I', 'I', 146 'I', 'D', 'N', 'O', 'O', 'O', 'O', 'O', 'O', 'U', 'U', 'U', 'U', 'Y', 'Th', 147 'ss', 'a', 'a', 'a', 'a', 'a', 'a', 'ae', 'c', 'e', 'e', 'e', 'e', 'i', 'i', 'i', 148 'i', 'd', 'n', 'o', 'o', 'o', 'o', 'o', 'o', 'u', 'u', 'u', 'u', 'y', 'th', 'y', 149 // Converted Latin Extended-A letters. 150 'A', 'a', 'A', 'a', 'A', 'a', 'C', 'c', 'C', 'c', 'C', 'c', 'C', 'c', 151 'D', 'd', 'D', 'd', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 152 'G', 'g', 'G', 'g', 'G', 'g', 'G', 'g', 'H', 'h', 'H', 'h', 153 'I', 'i', 'I', 'i', 'I', 'i', 'I', 'i', 'I', 'i', 'IJ', 'ij', 'J', 'j', 154 'K', 'k', 'k', 'L', 'l', 'L', 'l', 'L', 'l', 'L', 'l', 'L', 'l', 155 'N', 'n', 'N', 'n', 'N', 'n', "'n", 'N', 'n', 156 'O', 'o', 'O', 'o', 'O', 'o', 'Oe', 'oe', 157 'R', 'r', 'R', 'r', 'R', 'r', 'S', 's', 'S', 's', 'S', 's', 'S', 's', 158 'T', 't', 'T', 't', 'T', 't', 159 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 160 'W', 'w', 'Y', 'y', 'Y', 'Z', 'z', 'Z', 'z', 'Z', 'z', 's' 161 ]; 162 163 /** Used to provide falsey values to methods. */ 164 var falsey = [, null, undefined, false, 0, NaN, '']; 165 166 /** Used to specify the emoji style glyph variant of characters. */ 167 var emojiVar = '\ufe0f'; 168 169 /** Used to provide empty values to methods. */ 170 var empties = [[], {}].concat(falsey.slice(1)); 171 172 /** Used to test error objects. */ 173 var errors = [ 174 new Error, 175 new EvalError, 176 new RangeError, 177 new ReferenceError, 178 new SyntaxError, 179 new TypeError, 180 new URIError 181 ]; 182 183 /** List of fitzpatrick modifiers. */ 184 var fitzModifiers = [ 185 '\ud83c\udffb', 186 '\ud83c\udffc', 187 '\ud83c\udffd', 188 '\ud83c\udffe', 189 '\ud83c\udfff' 190 ]; 191 192 /** Used to provide primitive values to methods. */ 193 var primitives = [null, undefined, false, true, 1, NaN, 'a']; 194 195 /** Used to check whether methods support typed arrays. */ 196 var typedArrays = [ 197 'Float32Array', 198 'Float64Array', 199 'Int8Array', 200 'Int16Array', 201 'Int32Array', 202 'Uint8Array', 203 'Uint8ClampedArray', 204 'Uint16Array', 205 'Uint32Array' 206 ]; 207 208 /** Used to check whether methods support array views. */ 209 var arrayViews = typedArrays.concat('DataView'); 210 211 /** The file path of the lodash file to test. */ 212 var filePath = (function() { 213 var min = 2, 214 result = params || []; 215 216 if (phantom) { 217 min = 0; 218 result = params = phantom.args || require('system').args; 219 } 220 var last = result[result.length - 1]; 221 result = (result.length > min && !/test(?:\.js)?$/.test(last)) ? last : '../lodash.js'; 222 223 if (!amd) { 224 try { 225 result = require('fs').realpathSync(result); 226 } catch (e) {} 227 228 try { 229 result = require.resolve(result); 230 } catch (e) {} 231 } 232 return result; 233 }()); 234 235 /** The `ui` object. */ 236 var ui = root.ui || (root.ui = { 237 'buildPath': filePath, 238 'loaderPath': '', 239 'isModularize': /\b(?:amd|commonjs|es|node|npm|(index|main)\.js)\b/.test(filePath), 240 'isStrict': /\bes\b/.test(filePath) || 'default' in require(filePath), 241 'urlParams': {} 242 }); 243 244 /** The basename of the lodash file to test. */ 245 var basename = /[\w.-]+$/.exec(filePath)[0]; 246 247 /** Used to indicate testing a modularized build. */ 248 var isModularize = ui.isModularize; 249 250 /** Detect if testing `npm` modules. */ 251 var isNpm = isModularize && /\bnpm\b/.test([ui.buildPath, ui.urlParams.build]); 252 253 /** Detect if running in PhantomJS. */ 254 var isPhantom = phantom || (typeof callPhantom == 'function'); 255 256 /** Detect if lodash is in strict mode. */ 257 var isStrict = ui.isStrict; 258 259 /*--------------------------------------------------------------------------*/ 260 261 // Leak to avoid sporadic `noglobals` fails on Edge in Sauce Labs. 262 root.msWDfn = undefined; 263 264 // Assign `setTimeout` to itself to avoid being flagged as a leak. 265 setProperty(root, 'setTimeout', setTimeout); 266 267 // Exit early if going to run tests in a PhantomJS web page. 268 if (phantom && isModularize) { 269 var page = require('webpage').create(); 270 271 page.onCallback = function(details) { 272 var coverage = details.coverage; 273 if (coverage) { 274 var fs = require('fs'), 275 cwd = fs.workingDirectory, 276 sep = fs.separator; 277 278 fs.write([cwd, 'coverage', 'coverage.json'].join(sep), JSON.stringify(coverage)); 279 } 280 phantom.exit(details.failed ? 1 : 0); 281 }; 282 283 page.onConsoleMessage = function(message) { 284 console.log(message); 285 }; 286 287 page.onInitialized = function() { 288 page.evaluate(function() { 289 document.addEventListener('DOMContentLoaded', function() { 290 QUnit.done(function(details) { 291 details.coverage = window.__coverage__; 292 callPhantom(details); 293 }); 294 }); 295 }); 296 }; 297 298 page.open(filePath, function(status) { 299 if (status != 'success') { 300 console.log('PhantomJS failed to load page: ' + filePath); 301 phantom.exit(1); 302 } 303 }); 304 305 console.log('test.js invoked with arguments: ' + JSON.stringify(slice.call(params))); 306 return; 307 } 308 309 /*--------------------------------------------------------------------------*/ 310 311 /** Used to test Web Workers. */ 312 var Worker = !(ui.isForeign || ui.isSauceLabs || isModularize) && 313 (document && document.origin != 'null') && root.Worker; 314 315 /** Used to test host objects in IE. */ 316 try { 317 var xml = new ActiveXObject('Microsoft.XMLDOM'); 318 } catch (e) {} 319 320 /** Poison the free variable `root` in Node.js */ 321 try { 322 defineProperty(global.root, 'root', { 323 'configurable': false, 324 'enumerable': false, 325 'get': function() { throw new ReferenceError; } 326 }); 327 } catch (e) {} 328 329 /** Load QUnit and extras. */ 330 var QUnit = root.QUnit || require('qunit-extras'); 331 332 /** Load stable Lodash. */ 333 var lodashStable = root.lodashStable; 334 if (!lodashStable) { 335 try { 336 lodashStable = interopRequire('../node_modules/lodash/lodash.js'); 337 } catch (e) { 338 console.log('Error: The stable lodash dev dependency should be at least a version behind master branch.'); 339 return; 340 } 341 lodashStable = lodashStable.noConflict(); 342 } 343 344 /** The `lodash` function to test. */ 345 var _ = root._ || (root._ = interopRequire(filePath)); 346 347 /** Used to test pseudo private map caches. */ 348 var mapCaches = (function() { 349 var MapCache = (_.memoize || lodashStable.memoize).Cache; 350 var result = { 351 'Hash': new MapCache().__data__.hash.constructor, 352 'MapCache': MapCache 353 }; 354 (_.isMatchWith || lodashStable.isMatchWith)({ 'a': 1 }, { 'a': 1 }, function() { 355 var stack = lodashStable.last(arguments); 356 result.ListCache = stack.__data__.constructor; 357 result.Stack = stack.constructor; 358 }); 359 return result; 360 }()); 361 362 /** Used to detect instrumented istanbul code coverage runs. */ 363 var coverage = root.__coverage__ || root[lodashStable.find(lodashStable.keys(root), function(key) { 364 return /^(?:\$\$cov_\d+\$\$)$/.test(key); 365 })]; 366 367 /** Used to test async functions. */ 368 var asyncFunc = lodashStable.attempt(function() { 369 return Function('return async () => {}'); 370 }); 371 372 /** Used to test generator functions. */ 373 var genFunc = lodashStable.attempt(function() { 374 return Function('return function*(){}'); 375 }); 376 377 /** Used to restore the `_` reference. */ 378 var oldDash = root._; 379 380 /** 381 * Used to check for problems removing whitespace. For a whitespace reference, 382 * see [V8's unit test](https://code.google.com/p/v8/source/browse/branches/bleeding_edge/test/mjsunit/whitespaces.js). 383 */ 384 var whitespace = lodashStable.filter([ 385 // Basic whitespace characters. 386 ' ', '\t', '\x0b', '\f', '\xa0', '\ufeff', 387 388 // Line terminators. 389 '\n', '\r', '\u2028', '\u2029', 390 391 // Unicode category "Zs" space separators. 392 '\u1680', '\u180e', '\u2000', '\u2001', '\u2002', '\u2003', '\u2004', '\u2005', 393 '\u2006', '\u2007', '\u2008', '\u2009', '\u200a', '\u202f', '\u205f', '\u3000' 394 ], 395 function(chr) { return /\s/.exec(chr); }) 396 .join(''); 397 398 /** 399 * Creates a custom error object. 400 * 401 * @private 402 * @constructor 403 * @param {string} message The error message. 404 */ 405 function CustomError(message) { 406 this.name = 'CustomError'; 407 this.message = message; 408 } 409 410 CustomError.prototype = lodashStable.create(Error.prototype, { 411 'constructor': CustomError 412 }); 413 414 /** 415 * Removes all own enumerable string keyed properties from a given object. 416 * 417 * @private 418 * @param {Object} object The object to empty. 419 */ 420 function emptyObject(object) { 421 lodashStable.forOwn(object, function(value, key, object) { 422 delete object[key]; 423 }); 424 } 425 426 /** 427 * Extracts the unwrapped value from its wrapper. 428 * 429 * @private 430 * @param {Object} wrapper The wrapper to unwrap. 431 * @returns {*} Returns the unwrapped value. 432 */ 433 function getUnwrappedValue(wrapper) { 434 var index = -1, 435 actions = wrapper.__actions__, 436 length = actions.length, 437 result = wrapper.__wrapped__; 438 439 while (++index < length) { 440 var args = [result], 441 action = actions[index]; 442 443 push.apply(args, action.args); 444 result = action.func.apply(action.thisArg, args); 445 } 446 return result; 447 } 448 449 /** 450 * Loads the module of `id`. If the module has an `exports.default`, the 451 * exported default value is returned as the resolved module. 452 * 453 * @private 454 * @param {string} id The identifier of the module to resolve. 455 * @returns {*} Returns the resolved module. 456 */ 457 function interopRequire(id) { 458 var result = require(id); 459 return 'default' in result ? result['default'] : result; 460 } 461 462 /** 463 * Sets a non-enumerable property value on `object`. 464 * 465 * Note: This function is used to avoid a bug in older versions of V8 where 466 * overwriting non-enumerable built-ins makes them enumerable. 467 * See https://code.google.com/p/v8/issues/detail?id=1623 468 * 469 * @private 470 * @param {Object} object The object modify. 471 * @param {string} key The name of the property to set. 472 * @param {*} value The property value. 473 */ 474 function setProperty(object, key, value) { 475 try { 476 defineProperty(object, key, { 477 'configurable': true, 478 'enumerable': false, 479 'writable': true, 480 'value': value 481 }); 482 } catch (e) { 483 object[key] = value; 484 } 485 return object; 486 } 487 488 /** 489 * Skips a given number of tests with a passing result. 490 * 491 * @private 492 * @param {Object} assert The QUnit assert object. 493 * @param {number} [count=1] The number of tests to skip. 494 */ 495 function skipAssert(assert, count) { 496 count || (count = 1); 497 while (count--) { 498 assert.ok(true, 'test skipped'); 499 } 500 } 501 502 /** 503 * Converts `array` to an `arguments` object. 504 * 505 * @private 506 * @param {Array} array The array to convert. 507 * @returns {Object} Returns the converted `arguments` object. 508 */ 509 function toArgs(array) { 510 return (function() { return arguments; }.apply(undefined, array)); 511 } 512 513 /*--------------------------------------------------------------------------*/ 514 515 // Add bizarro values. 516 (function() { 517 if (document || (typeof require != 'function')) { 518 return; 519 } 520 var nativeString = fnToString.call(toString), 521 reToString = /toString/g; 522 523 function createToString(funcName) { 524 return lodashStable.constant(nativeString.replace(reToString, funcName)); 525 } 526 527 // Allow bypassing native checks. 528 setProperty(funcProto, 'toString', function wrapper() { 529 setProperty(funcProto, 'toString', fnToString); 530 var result = lodashStable.has(this, 'toString') ? this.toString() : fnToString.call(this); 531 setProperty(funcProto, 'toString', wrapper); 532 return result; 533 }); 534 535 // Add prototype extensions. 536 funcProto._method = noop; 537 538 // Set bad shims. 539 setProperty(Object, 'create', undefined); 540 setProperty(Object, 'getOwnPropertySymbols', undefined); 541 542 var _propertyIsEnumerable = objectProto.propertyIsEnumerable; 543 setProperty(objectProto, 'propertyIsEnumerable', function(key) { 544 return !(key == 'valueOf' && this && this.valueOf === 1) && _propertyIsEnumerable.call(this, key); 545 }); 546 547 if (Buffer) { 548 defineProperty(root, 'Buffer', { 549 'configurable': true, 550 'enumerable': true, 551 'get': function get() { 552 var caller = get.caller, 553 name = caller ? caller.name : ''; 554 555 if (!(name == 'runInContext' || name.length == 1 || /\b_\.isBuffer\b/.test(caller))) { 556 return Buffer; 557 } 558 } 559 }); 560 } 561 if (Map) { 562 setProperty(root, 'Map', (function() { 563 var count = 0; 564 return function() { 565 if (count++) { 566 return new Map; 567 } 568 setProperty(root, 'Map', Map); 569 return {}; 570 }; 571 }())); 572 573 setProperty(root.Map, 'toString', createToString('Map')); 574 } 575 setProperty(root, 'Promise', noop); 576 setProperty(root, 'Set', noop); 577 setProperty(root, 'Symbol', undefined); 578 setProperty(root, 'WeakMap', noop); 579 580 // Fake `WinRTError`. 581 setProperty(root, 'WinRTError', Error); 582 583 // Clear cache so lodash can be reloaded. 584 emptyObject(require.cache); 585 586 // Load lodash and expose it to the bad extensions/shims. 587 lodashBizarro = interopRequire(filePath); 588 root._ = oldDash; 589 590 // Restore built-in methods. 591 setProperty(Object, 'create', create); 592 setProperty(objectProto, 'propertyIsEnumerable', _propertyIsEnumerable); 593 setProperty(root, 'Buffer', Buffer); 594 595 if (getSymbols) { 596 Object.getOwnPropertySymbols = getSymbols; 597 } else { 598 delete Object.getOwnPropertySymbols; 599 } 600 if (Map) { 601 setProperty(root, 'Map', Map); 602 } else { 603 delete root.Map; 604 } 605 if (Promise) { 606 setProperty(root, 'Promise', Promise); 607 } else { 608 delete root.Promise; 609 } 610 if (Set) { 611 setProperty(root, 'Set', Set); 612 } else { 613 delete root.Set; 614 } 615 if (Symbol) { 616 setProperty(root, 'Symbol', Symbol); 617 } else { 618 delete root.Symbol; 619 } 620 if (WeakMap) { 621 setProperty(root, 'WeakMap', WeakMap); 622 } else { 623 delete root.WeakMap; 624 } 625 delete root.WinRTError; 626 delete funcProto._method; 627 }()); 628 629 // Add other realm values from the `vm` module. 630 lodashStable.attempt(function() { 631 lodashStable.assign(realm, require('vm').runInNewContext([ 632 '(function() {', 633 ' var noop = function() {},', 634 ' root = this;', 635 '', 636 ' var object = {', 637 " 'ArrayBuffer': root.ArrayBuffer,", 638 " 'arguments': (function() { return arguments; }(1, 2, 3)),", 639 " 'array': [1],", 640 " 'arrayBuffer': root.ArrayBuffer ? new root.ArrayBuffer : undefined,", 641 " 'boolean': Object(false),", 642 " 'date': new Date,", 643 " 'errors': [new Error, new EvalError, new RangeError, new ReferenceError, new SyntaxError, new TypeError, new URIError],", 644 " 'function': noop,", 645 " 'map': root.Map ? new root.Map : undefined,", 646 " 'nan': NaN,", 647 " 'null': null,", 648 " 'number': Object(0),", 649 " 'object': { 'a': 1 },", 650 " 'promise': root.Promise ? Promise.resolve(1) : undefined,", 651 " 'regexp': /x/,", 652 " 'set': root.Set ? new root.Set : undefined,", 653 " 'string': Object('a'),", 654 " 'symbol': root.Symbol ? root.Symbol() : undefined,", 655 " 'undefined': undefined,", 656 " 'weakMap': root.WeakMap ? new root.WeakMap : undefined,", 657 " 'weakSet': root.WeakSet ? new root.WeakSet : undefined", 658 ' };', 659 '', 660 " ['" + arrayViews.join("', '") + "'].forEach(function(type) {", 661 ' var Ctor = root[type]', 662 ' object[type] = Ctor;', 663 ' object[type.toLowerCase()] = Ctor ? new Ctor(new ArrayBuffer(24)) : undefined;', 664 ' });', 665 '', 666 ' return object;', 667 '}());' 668 ].join('\n'))); 669 }); 670 671 // Add other realm values from an iframe. 672 lodashStable.attempt(function() { 673 _._realm = realm; 674 675 var iframe = document.createElement('iframe'); 676 iframe.frameBorder = iframe.height = iframe.width = 0; 677 body.appendChild(iframe); 678 679 var idoc = (idoc = iframe.contentDocument || iframe.contentWindow).document || idoc; 680 idoc.write([ 681 '<html>', 682 '<body>', 683 '<script>', 684 'var _ = parent._,', 685 ' noop = function() {},', 686 ' root = this;', 687 '', 688 'var object = {', 689 " 'ArrayBuffer': root.ArrayBuffer,", 690 " 'arguments': (function() { return arguments; }(1, 2, 3)),", 691 " 'array': [1],", 692 " 'arrayBuffer': root.ArrayBuffer ? new root.ArrayBuffer : undefined,", 693 " 'boolean': Object(false),", 694 " 'date': new Date,", 695 " 'element': document.body,", 696 " 'errors': [new Error, new EvalError, new RangeError, new ReferenceError, new SyntaxError, new TypeError, new URIError],", 697 " 'function': noop,", 698 " 'map': root.Map ? new root.Map : undefined,", 699 " 'nan': NaN,", 700 " 'null': null,", 701 " 'number': Object(0),", 702 " 'object': { 'a': 1 },", 703 " 'promise': root.Promise ? Promise.resolve(1) : undefined,", 704 " 'regexp': /x/,", 705 " 'set': root.Set ? new root.Set : undefined,", 706 " 'string': Object('a'),", 707 " 'symbol': root.Symbol ? root.Symbol() : undefined,", 708 " 'undefined': undefined,", 709 " 'weakMap': root.WeakMap ? new root.WeakMap : undefined,", 710 " 'weakSet': root.WeakSet ? new root.WeakSet : undefined", 711 '};', 712 '', 713 "_.each(['" + arrayViews.join("', '") + "'], function(type) {", 714 ' var Ctor = root[type];', 715 ' object[type] = Ctor;', 716 ' object[type.toLowerCase()] = Ctor ? new Ctor(new ArrayBuffer(24)) : undefined;', 717 '});', 718 '', 719 '_.assign(_._realm, object);', 720 '</script>', 721 '</body>', 722 '</html>' 723 ].join('\n')); 724 725 idoc.close(); 726 delete _._realm; 727 }); 728 729 // Add a web worker. 730 lodashStable.attempt(function() { 731 var worker = new Worker('./asset/worker.js?t=' + (+new Date)); 732 worker.addEventListener('message', function(e) { 733 _._VERSION = e.data || ''; 734 }, false); 735 736 worker.postMessage(ui.buildPath); 737 }); 738 739 // Expose internal modules for better code coverage. 740 lodashStable.attempt(function() { 741 var path = require('path'), 742 basePath = path.dirname(filePath); 743 744 if (isModularize && !(amd || isNpm)) { 745 lodashStable.each([ 746 'baseEach', 747 'isIndex', 748 'isIterateeCall', 749 'memoizeCapped' 750 ], function(funcName) { 751 _['_' + funcName] = interopRequire(path.join(basePath, '_' + funcName)); 752 }); 753 } 754 }); 755 756 /*--------------------------------------------------------------------------*/ 757 758 if (params) { 759 console.log('Running lodash tests.'); 760 console.log('test.js invoked with arguments: ' + JSON.stringify(slice.call(params))); 761 } 762 763 QUnit.module(basename); 764 765 (function() { 766 QUnit.test('should support loading ' + basename + ' as the "lodash" module', function(assert) { 767 assert.expect(1); 768 769 if (amd) { 770 assert.strictEqual((lodashModule || {}).moduleName, 'lodash'); 771 } 772 else { 773 skipAssert(assert); 774 } 775 }); 776 777 QUnit.test('should support loading ' + basename + ' with the Require.js "shim" configuration option', function(assert) { 778 assert.expect(1); 779 780 if (amd && lodashStable.includes(ui.loaderPath, 'requirejs')) { 781 assert.strictEqual((shimmedModule || {}).moduleName, 'shimmed'); 782 } else { 783 skipAssert(assert); 784 } 785 }); 786 787 QUnit.test('should support loading ' + basename + ' as the "underscore" module', function(assert) { 788 assert.expect(1); 789 790 if (amd) { 791 assert.strictEqual((underscoreModule || {}).moduleName, 'underscore'); 792 } 793 else { 794 skipAssert(assert); 795 } 796 }); 797 798 QUnit.test('should support loading ' + basename + ' in a web worker', function(assert) { 799 assert.expect(1); 800 801 var done = assert.async(); 802 803 if (Worker) { 804 var limit = 30000 / QUnit.config.asyncRetries, 805 start = +new Date; 806 807 var attempt = function() { 808 var actual = _._VERSION; 809 if ((new Date - start) < limit && typeof actual != 'string') { 810 setTimeout(attempt, 16); 811 return; 812 } 813 assert.strictEqual(actual, _.VERSION); 814 done(); 815 }; 816 817 attempt(); 818 } 819 else { 820 skipAssert(assert); 821 done(); 822 } 823 }); 824 825 QUnit.test('should not add `Function.prototype` extensions to lodash', function(assert) { 826 assert.expect(1); 827 828 if (lodashBizarro) { 829 assert.notOk('_method' in lodashBizarro); 830 } 831 else { 832 skipAssert(assert); 833 } 834 }); 835 836 QUnit.test('should avoid non-native built-ins', function(assert) { 837 assert.expect(6); 838 839 function message(lodashMethod, nativeMethod) { 840 return '`' + lodashMethod + '` should avoid overwritten native `' + nativeMethod + '`'; 841 } 842 843 function Foo() { 844 this.a = 1; 845 } 846 Foo.prototype.b = 2; 847 848 var object = { 'a': 1 }, 849 otherObject = { 'b': 2 }, 850 largeArray = lodashStable.times(LARGE_ARRAY_SIZE, lodashStable.constant(object)); 851 852 if (lodashBizarro) { 853 try { 854 var actual = lodashBizarro.create(Foo.prototype); 855 } catch (e) { 856 actual = null; 857 } 858 var label = message('_.create', 'Object.create'); 859 assert.ok(actual instanceof Foo, label); 860 861 try { 862 actual = [ 863 lodashBizarro.difference([object, otherObject], largeArray), 864 lodashBizarro.intersection(largeArray, [object]), 865 lodashBizarro.uniq(largeArray) 866 ]; 867 } catch (e) { 868 actual = null; 869 } 870 label = message('_.difference`, `_.intersection`, and `_.uniq', 'Map'); 871 assert.deepEqual(actual, [[otherObject], [object], [object]], label); 872 873 try { 874 if (Symbol) { 875 object[symbol] = {}; 876 } 877 actual = [ 878 lodashBizarro.clone(object), 879 lodashBizarro.cloneDeep(object) 880 ]; 881 } catch (e) { 882 actual = null; 883 } 884 label = message('_.clone` and `_.cloneDeep', 'Object.getOwnPropertySymbols'); 885 assert.deepEqual(actual, [object, object], label); 886 887 try { 888 // Avoid buggy symbol detection in Babel's `_typeof` helper. 889 var symObject = setProperty(Object(symbol), 'constructor', Object); 890 actual = [ 891 Symbol ? lodashBizarro.clone(symObject) : {}, 892 Symbol ? lodashBizarro.isEqual(symObject, Object(symbol)) : false, 893 Symbol ? lodashBizarro.toString(symObject) : '' 894 ]; 895 } catch (e) { 896 actual = null; 897 } 898 label = message('_.clone`, `_.isEqual`, and `_.toString', 'Symbol'); 899 assert.deepEqual(actual, [{}, false, ''], label); 900 901 try { 902 var map = new lodashBizarro.memoize.Cache; 903 actual = map.set('a', 1).get('a'); 904 } catch (e) { 905 actual = null; 906 } 907 label = message('_.memoize.Cache', 'Map'); 908 assert.deepEqual(actual, 1, label); 909 910 try { 911 map = new (Map || Object); 912 if (Symbol && Symbol.iterator) { 913 map[Symbol.iterator] = null; 914 } 915 actual = lodashBizarro.toArray(map); 916 } catch (e) { 917 actual = null; 918 } 919 label = message('_.toArray', 'Map'); 920 assert.deepEqual(actual, [], label); 921 } 922 else { 923 skipAssert(assert, 6); 924 } 925 }); 926 }()); 927 928 /*--------------------------------------------------------------------------*/ 929 930 QUnit.module('isIndex'); 931 932 (function() { 933 var func = _._isIndex; 934 935 QUnit.test('should return `true` for indexes', function(assert) { 936 assert.expect(1); 937 938 if (func) { 939 var values = [[0], ['0'], ['1'], [3, 4], [MAX_SAFE_INTEGER - 1]], 940 expected = lodashStable.map(values, stubTrue); 941 942 var actual = lodashStable.map(values, function(args) { 943 return func.apply(undefined, args); 944 }); 945 946 assert.deepEqual(actual, expected); 947 } 948 else { 949 skipAssert(assert); 950 } 951 }); 952 953 QUnit.test('should return `false` for non-indexes', function(assert) { 954 assert.expect(1); 955 956 if (func) { 957 var values = [['1abc'], ['07'], ['0001'], [-1], [3, 3], [1.1], [MAX_SAFE_INTEGER]], 958 expected = lodashStable.map(values, stubFalse); 959 960 var actual = lodashStable.map(values, function(args) { 961 return func.apply(undefined, args); 962 }); 963 964 assert.deepEqual(actual, expected); 965 } 966 else { 967 skipAssert(assert); 968 } 969 }); 970 }()); 971 972 /*--------------------------------------------------------------------------*/ 973 974 QUnit.module('isIterateeCall'); 975 976 (function() { 977 var array = [1], 978 func = _._isIterateeCall, 979 object = { 'a': 1 }; 980 981 QUnit.test('should return `true` for iteratee calls', function(assert) { 982 assert.expect(3); 983 984 function Foo() {} 985 Foo.prototype.a = 1; 986 987 if (func) { 988 assert.strictEqual(func(1, 0, array), true); 989 assert.strictEqual(func(1, 'a', object), true); 990 assert.strictEqual(func(1, 'a', new Foo), true); 991 } 992 else { 993 skipAssert(assert, 3); 994 } 995 }); 996 997 QUnit.test('should return `false` for non-iteratee calls', function(assert) { 998 assert.expect(4); 999 1000 if (func) { 1001 assert.strictEqual(func(2, 0, array), false); 1002 assert.strictEqual(func(1, 1.1, array), false); 1003 assert.strictEqual(func(1, 0, { 'length': MAX_SAFE_INTEGER + 1 }), false); 1004 assert.strictEqual(func(1, 'b', object), false); 1005 } 1006 else { 1007 skipAssert(assert, 4); 1008 } 1009 }); 1010 1011 QUnit.test('should work with `NaN` values', function(assert) { 1012 assert.expect(2); 1013 1014 if (func) { 1015 assert.strictEqual(func(NaN, 0, [NaN]), true); 1016 assert.strictEqual(func(NaN, 'a', { 'a': NaN }), true); 1017 } 1018 else { 1019 skipAssert(assert, 2); 1020 } 1021 }); 1022 1023 QUnit.test('should not error when `index` is an object without a `toString` method', function(assert) { 1024 assert.expect(1); 1025 1026 if (func) { 1027 try { 1028 var actual = func(1, { 'toString': null }, [1]); 1029 } catch (e) { 1030 var message = e.message; 1031 } 1032 assert.strictEqual(actual, false, message || ''); 1033 } 1034 else { 1035 skipAssert(assert); 1036 } 1037 }); 1038 }()); 1039 1040 /*--------------------------------------------------------------------------*/ 1041 1042 QUnit.module('map caches'); 1043 1044 (function() { 1045 var keys = [null, undefined, false, true, 1, -Infinity, NaN, {}, 'a', symbol || noop]; 1046 1047 var pairs = lodashStable.map(keys, function(key, index) { 1048 var lastIndex = keys.length - 1; 1049 return [key, keys[lastIndex - index]]; 1050 }); 1051 1052 function createCaches(pairs) { 1053 var largeStack = new mapCaches.Stack(pairs), 1054 length = pairs ? pairs.length : 0; 1055 1056 lodashStable.times(LARGE_ARRAY_SIZE - length, function() { 1057 largeStack.set({}, {}); 1058 }); 1059 1060 return { 1061 'hashes': new mapCaches.Hash(pairs), 1062 'list caches': new mapCaches.ListCache(pairs), 1063 'map caches': new mapCaches.MapCache(pairs), 1064 'stack caches': new mapCaches.Stack(pairs), 1065 'large stacks': largeStack 1066 }; 1067 } 1068 1069 lodashStable.forOwn(createCaches(pairs), function(cache, kind) { 1070 var isLarge = /^large/.test(kind); 1071 1072 QUnit.test('should implement a `Map` interface for ' + kind, function(assert) { 1073 assert.expect(83); 1074 1075 lodashStable.each(keys, function(key, index) { 1076 var value = pairs[index][1]; 1077 1078 assert.deepEqual(cache.get(key), value); 1079 assert.strictEqual(cache.has(key), true); 1080 assert.strictEqual(cache.delete(key), true); 1081 assert.strictEqual(cache.has(key), false); 1082 assert.strictEqual(cache.get(key), undefined); 1083 assert.strictEqual(cache.delete(key), false); 1084 assert.strictEqual(cache.set(key, value), cache); 1085 assert.strictEqual(cache.has(key), true); 1086 }); 1087 1088 assert.strictEqual(cache.size, isLarge ? LARGE_ARRAY_SIZE : keys.length); 1089 assert.strictEqual(cache.clear(), undefined); 1090 assert.ok(lodashStable.every(keys, function(key) { 1091 return !cache.has(key); 1092 })); 1093 }); 1094 }); 1095 1096 lodashStable.forOwn(createCaches(), function(cache, kind) { 1097 QUnit.test('should support changing values of ' + kind, function(assert) { 1098 assert.expect(10); 1099 1100 lodashStable.each(keys, function(key) { 1101 cache.set(key, 1).set(key, 2); 1102 assert.strictEqual(cache.get(key), 2); 1103 }); 1104 }); 1105 }); 1106 }()); 1107 1108 /*--------------------------------------------------------------------------*/ 1109 1110 QUnit.module('lodash constructor'); 1111 1112 (function() { 1113 var values = empties.concat(true, 1, 'a'), 1114 expected = lodashStable.map(values, stubTrue); 1115 1116 QUnit.test('should create a new instance when called without the `new` operator', function(assert) { 1117 assert.expect(1); 1118 1119 if (!isNpm) { 1120 var actual = lodashStable.map(values, function(value) { 1121 return _(value) instanceof _; 1122 }); 1123 1124 assert.deepEqual(actual, expected); 1125 } 1126 else { 1127 skipAssert(assert); 1128 } 1129 }); 1130 1131 QUnit.test('should return the given `lodash` instances', function(assert) { 1132 assert.expect(1); 1133 1134 if (!isNpm) { 1135 var actual = lodashStable.map(values, function(value) { 1136 var wrapped = _(value); 1137 return _(wrapped) === wrapped; 1138 }); 1139 1140 assert.deepEqual(actual, expected); 1141 } 1142 else { 1143 skipAssert(assert); 1144 } 1145 }); 1146 1147 QUnit.test('should convert foreign wrapped values to `lodash` instances', function(assert) { 1148 assert.expect(1); 1149 1150 if (!isNpm && lodashBizarro) { 1151 var actual = lodashStable.map(values, function(value) { 1152 var wrapped = _(lodashBizarro(value)), 1153 unwrapped = wrapped.value(); 1154 1155 return wrapped instanceof _ && 1156 ((unwrapped === value) || (unwrapped !== unwrapped && value !== value)); 1157 }); 1158 1159 assert.deepEqual(actual, expected); 1160 } 1161 else { 1162 skipAssert(assert); 1163 } 1164 }); 1165 }()); 1166 1167 /*--------------------------------------------------------------------------*/ 1168 1169 QUnit.module('lodash.add'); 1170 1171 (function() { 1172 QUnit.test('should add two numbers', function(assert) { 1173 assert.expect(3); 1174 1175 assert.strictEqual(_.add(6, 4), 10); 1176 assert.strictEqual(_.add(-6, 4), -2); 1177 assert.strictEqual(_.add(-6, -4), -10); 1178 }); 1179 1180 QUnit.test('should not coerce arguments to numbers', function(assert) { 1181 assert.expect(2); 1182 1183 assert.strictEqual(_.add('6', '4'), '64'); 1184 assert.strictEqual(_.add('x', 'y'), 'xy'); 1185 }); 1186 }()); 1187 1188 /*--------------------------------------------------------------------------*/ 1189 1190 QUnit.module('lodash.after'); 1191 1192 (function() { 1193 function after(n, times) { 1194 var count = 0; 1195 lodashStable.times(times, _.after(n, function() { count++; })); 1196 return count; 1197 } 1198 1199 QUnit.test('should create a function that invokes `func` after `n` calls', function(assert) { 1200 assert.expect(4); 1201 1202 assert.strictEqual(after(5, 5), 1, 'after(n) should invoke `func` after being called `n` times'); 1203 assert.strictEqual(after(5, 4), 0, 'after(n) should not invoke `func` before being called `n` times'); 1204 assert.strictEqual(after(0, 0), 0, 'after(0) should not invoke `func` immediately'); 1205 assert.strictEqual(after(0, 1), 1, 'after(0) should invoke `func` when called once'); 1206 }); 1207 1208 QUnit.test('should coerce `n` values of `NaN` to `0`', function(assert) { 1209 assert.expect(1); 1210 1211 assert.strictEqual(after(NaN, 1), 1); 1212 }); 1213 1214 QUnit.test('should use `this` binding of function', function(assert) { 1215 assert.expect(2); 1216 1217 var after = _.after(1, function(assert) { return ++this.count; }), 1218 object = { 'after': after, 'count': 0 }; 1219 1220 object.after(); 1221 assert.strictEqual(object.after(), 2); 1222 assert.strictEqual(object.count, 2); 1223 }); 1224 }()); 1225 1226 /*--------------------------------------------------------------------------*/ 1227 1228 QUnit.module('lodash.ary'); 1229 1230 (function() { 1231 function fn(a, b, c) { 1232 return slice.call(arguments); 1233 } 1234 1235 QUnit.test('should cap the number of arguments provided to `func`', function(assert) { 1236 assert.expect(2); 1237 1238 var actual = lodashStable.map(['6', '8', '10'], _.ary(parseInt, 1)); 1239 assert.deepEqual(actual, [6, 8, 10]); 1240 1241 var capped = _.ary(fn, 2); 1242 assert.deepEqual(capped('a', 'b', 'c', 'd'), ['a', 'b']); 1243 }); 1244 1245 QUnit.test('should use `func.length` if `n` is not given', function(assert) { 1246 assert.expect(1); 1247 1248 var capped = _.ary(fn); 1249 assert.deepEqual(capped('a', 'b', 'c', 'd'), ['a', 'b', 'c']); 1250 }); 1251 1252 QUnit.test('should treat a negative `n` as `0`', function(assert) { 1253 assert.expect(1); 1254 1255 var capped = _.ary(fn, -1); 1256 1257 try { 1258 var actual = capped('a'); 1259 } catch (e) {} 1260 1261 assert.deepEqual(actual, []); 1262 }); 1263 1264 QUnit.test('should coerce `n` to an integer', function(assert) { 1265 assert.expect(1); 1266 1267 var values = ['1', 1.6, 'xyz'], 1268 expected = [['a'], ['a'], []]; 1269 1270 var actual = lodashStable.map(values, function(n) { 1271 var capped = _.ary(fn, n); 1272 return capped('a', 'b'); 1273 }); 1274 1275 assert.deepEqual(actual, expected); 1276 }); 1277 1278 QUnit.test('should not force a minimum argument count', function(assert) { 1279 assert.expect(1); 1280 1281 var args = ['a', 'b', 'c'], 1282 capped = _.ary(fn, 3); 1283 1284 var expected = lodashStable.map(args, function(arg, index) { 1285 return args.slice(0, index); 1286 }); 1287 1288 var actual = lodashStable.map(expected, function(array) { 1289 return capped.apply(undefined, array); 1290 }); 1291 1292 assert.deepEqual(actual, expected); 1293 }); 1294 1295 QUnit.test('should use `this` binding of function', function(assert) { 1296 assert.expect(1); 1297 1298 var capped = _.ary(function(a, b) { return this; }, 1), 1299 object = { 'capped': capped }; 1300 1301 assert.strictEqual(object.capped(), object); 1302 }); 1303 1304 QUnit.test('should use the existing `ary` if smaller', function(assert) { 1305 assert.expect(1); 1306 1307 var capped = _.ary(_.ary(fn, 1), 2); 1308 assert.deepEqual(capped('a', 'b', 'c'), ['a']); 1309 }); 1310 1311 QUnit.test('should work as an iteratee for methods like `_.map`', function(assert) { 1312 assert.expect(1); 1313 1314 var funcs = lodashStable.map([fn], _.ary), 1315 actual = funcs[0]('a', 'b', 'c'); 1316 1317 assert.deepEqual(actual, ['a', 'b', 'c']); 1318 }); 1319 1320 QUnit.test('should work when combined with other methods that use metadata', function(assert) { 1321 assert.expect(2); 1322 1323 var array = ['a', 'b', 'c'], 1324 includes = _.curry(_.rearg(_.ary(_.includes, 2), 1, 0), 2); 1325 1326 assert.strictEqual(includes('b')(array, 2), true); 1327 1328 if (!isNpm) { 1329 includes = _(_.includes).ary(2).rearg(1, 0).curry(2).value(); 1330 assert.strictEqual(includes('b')(array, 2), true); 1331 } 1332 else { 1333 skipAssert(assert); 1334 } 1335 }); 1336 }()); 1337 1338 /*--------------------------------------------------------------------------*/ 1339 1340 QUnit.module('lodash.assignIn'); 1341 1342 (function() { 1343 QUnit.test('should be aliased', function(assert) { 1344 assert.expect(1); 1345 1346 assert.strictEqual(_.extend, _.assignIn); 1347 }); 1348 }()); 1349 1350 /*--------------------------------------------------------------------------*/ 1351 1352 QUnit.module('lodash.assign and lodash.assignIn'); 1353 1354 lodashStable.each(['assign', 'assignIn'], function(methodName) { 1355 var func = _[methodName]; 1356 1357 QUnit.test('`_.' + methodName + '` should assign source properties to `object`', function(assert) { 1358 assert.expect(1); 1359 1360 assert.deepEqual(func({ 'a': 1 }, { 'b': 2 }), { 'a': 1, 'b': 2 }); 1361 }); 1362 1363 QUnit.test('`_.' + methodName + '` should accept multiple sources', function(assert) { 1364 assert.expect(2); 1365 1366 var expected = { 'a': 1, 'b': 2, 'c': 3 }; 1367 assert.deepEqual(func({ 'a': 1 }, { 'b': 2 }, { 'c': 3 }), expected); 1368 assert.deepEqual(func({ 'a': 1 }, { 'b': 2, 'c': 2 }, { 'c': 3 }), expected); 1369 }); 1370 1371 QUnit.test('`_.' + methodName + '` should overwrite destination properties', function(assert) { 1372 assert.expect(1); 1373 1374 var expected = { 'a': 3, 'b': 2, 'c': 1 }; 1375 assert.deepEqual(func({ 'a': 1, 'b': 2 }, expected), expected); 1376 }); 1377 1378 QUnit.test('`_.' + methodName + '` should assign source properties with nullish values', function(assert) { 1379 assert.expect(1); 1380 1381 var expected = { 'a': null, 'b': undefined, 'c': null }; 1382 assert.deepEqual(func({ 'a': 1, 'b': 2 }, expected), expected); 1383 }); 1384 1385 QUnit.test('`_.' + methodName + '` should skip assignments if values are the same', function(assert) { 1386 assert.expect(1); 1387 1388 var object = {}; 1389 1390 var descriptor = { 1391 'configurable': true, 1392 'enumerable': true, 1393 'set': function() { throw new Error; } 1394 }; 1395 1396 var source = { 1397 'a': 1, 1398 'b': undefined, 1399 'c': NaN, 1400 'd': undefined, 1401 'constructor': Object, 1402 'toString': lodashStable.constant('source') 1403 }; 1404 1405 defineProperty(object, 'a', lodashStable.assign({}, descriptor, { 1406 'get': stubOne 1407 })); 1408 1409 defineProperty(object, 'b', lodashStable.assign({}, descriptor, { 1410 'get': noop 1411 })); 1412 1413 defineProperty(object, 'c', lodashStable.assign({}, descriptor, { 1414 'get': stubNaN 1415 })); 1416 1417 defineProperty(object, 'constructor', lodashStable.assign({}, descriptor, { 1418 'get': lodashStable.constant(Object) 1419 })); 1420 1421 try { 1422 var actual = func(object, source); 1423 } catch (e) {} 1424 1425 assert.deepEqual(actual, source); 1426 }); 1427 1428 QUnit.test('`_.' + methodName + '` should treat sparse array sources as dense', function(assert) { 1429 assert.expect(1); 1430 1431 var array = [1]; 1432 array[2] = 3; 1433 1434 assert.deepEqual(func({}, array), { '0': 1, '1': undefined, '2': 3 }); 1435 }); 1436 1437 QUnit.test('`_.' + methodName + '` should assign values of prototype objects', function(assert) { 1438 assert.expect(1); 1439 1440 function Foo() {} 1441 Foo.prototype.a = 1; 1442 1443 assert.deepEqual(func({}, Foo.prototype), { 'a': 1 }); 1444 }); 1445 1446 QUnit.test('`_.' + methodName + '` should coerce string sources to objects', function(assert) { 1447 assert.expect(1); 1448 1449 assert.deepEqual(func({}, 'a'), { '0': 'a' }); 1450 }); 1451 }); 1452 1453 /*--------------------------------------------------------------------------*/ 1454 1455 QUnit.module('lodash.assignInWith'); 1456 1457 (function() { 1458 QUnit.test('should be aliased', function(assert) { 1459 assert.expect(1); 1460 1461 assert.strictEqual(_.extendWith, _.assignInWith); 1462 }); 1463 }()); 1464 1465 /*--------------------------------------------------------------------------*/ 1466 1467 QUnit.module('lodash.assignWith and lodash.assignInWith'); 1468 1469 lodashStable.each(['assignWith', 'assignInWith'], function(methodName) { 1470 var func = _[methodName]; 1471 1472 QUnit.test('`_.' + methodName + '` should work with a `customizer` callback', function(assert) { 1473 assert.expect(1); 1474 1475 var actual = func({ 'a': 1, 'b': 2 }, { 'a': 3, 'c': 3 }, function(a, b) { 1476 return a === undefined ? b : a; 1477 }); 1478 1479 assert.deepEqual(actual, { 'a': 1, 'b': 2, 'c': 3 }); 1480 }); 1481 1482 QUnit.test('`_.' + methodName + '` should work with a `customizer` that returns `undefined`', function(assert) { 1483 assert.expect(1); 1484 1485 var expected = { 'a': 1 }; 1486 assert.deepEqual(func({}, expected, noop), expected); 1487 }); 1488 }); 1489 1490 /*--------------------------------------------------------------------------*/ 1491 1492 QUnit.module('lodash.at'); 1493 1494 (function() { 1495 var array = ['a', 'b', 'c'], 1496 object = { 'a': [{ 'b': { 'c': 3 } }, 4] }; 1497 1498 QUnit.test('should return the elements corresponding to the specified keys', function(assert) { 1499 assert.expect(1); 1500 1501 var actual = _.at(array, [0, 2]); 1502 assert.deepEqual(actual, ['a', 'c']); 1503 }); 1504 1505 QUnit.test('should return `undefined` for nonexistent keys', function(assert) { 1506 assert.expect(1); 1507 1508 var actual = _.at(array, [2, 4, 0]); 1509 assert.deepEqual(actual, ['c', undefined, 'a']); 1510 }); 1511 1512 QUnit.test('should work with non-index keys on array values', function(assert) { 1513 assert.expect(1); 1514 1515 var values = lodashStable.reject(empties, function(value) { 1516 return (value === 0) || lodashStable.isArray(value); 1517 }).concat(-1, 1.1); 1518 1519 var array = lodashStable.transform(values, function(result, value) { 1520 result[value] = 1; 1521 }, []); 1522 1523 var expected = lodashStable.map(values, stubOne), 1524 actual = _.at(array, values); 1525 1526 assert.deepEqual(actual, expected); 1527 }); 1528 1529 QUnit.test('should return an empty array when no keys are given', function(assert) { 1530 assert.expect(2); 1531 1532 assert.deepEqual(_.at(array), []); 1533 assert.deepEqual(_.at(array, [], []), []); 1534 }); 1535 1536 QUnit.test('should accept multiple key arguments', function(assert) { 1537 assert.expect(1); 1538 1539 var actual = _.at(['a', 'b', 'c', 'd'], 3, 0, 2); 1540 assert.deepEqual(actual, ['d', 'a', 'c']); 1541 }); 1542 1543 QUnit.test('should work with a falsey `object` when keys are given', function(assert) { 1544 assert.expect(1); 1545 1546 var expected = lodashStable.map(falsey, lodashStable.constant(Array(4))); 1547 1548 var actual = lodashStable.map(falsey, function(object) { 1549 try { 1550 return _.at(object, 0, 1, 'pop', 'push'); 1551 } catch (e) {} 1552 }); 1553 1554 assert.deepEqual(actual, expected); 1555 }); 1556 1557 QUnit.test('should work with an `arguments` object for `object`', function(assert) { 1558 assert.expect(1); 1559 1560 var actual = _.at(args, [2, 0]); 1561 assert.deepEqual(actual, [3, 1]); 1562 }); 1563 1564 QUnit.test('should work with `arguments` object as secondary arguments', function(assert) { 1565 assert.expect(1); 1566 1567 var actual = _.at([1, 2, 3, 4, 5], args); 1568 assert.deepEqual(actual, [2, 3, 4]); 1569 }); 1570 1571 QUnit.test('should work with an object for `object`', function(assert) { 1572 assert.expect(1); 1573 1574 var actual = _.at(object, ['a[0].b.c', 'a[1]']); 1575 assert.deepEqual(actual, [3, 4]); 1576 }); 1577 1578 QUnit.test('should pluck inherited property values', function(assert) { 1579 assert.expect(1); 1580 1581 function Foo() { 1582 this.a = 1; 1583 } 1584 Foo.prototype.b = 2; 1585 1586 var actual = _.at(new Foo, 'b'); 1587 assert.deepEqual(actual, [2]); 1588 }); 1589 1590 QUnit.test('should work in a lazy sequence', function(assert) { 1591 assert.expect(6); 1592 1593 if (!isNpm) { 1594 var largeArray = lodashStable.range(LARGE_ARRAY_SIZE), 1595 smallArray = array; 1596 1597 lodashStable.each([[2], ['2'], [2, 1]], function(paths) { 1598 lodashStable.times(2, function(index) { 1599 var array = index ? largeArray : smallArray, 1600 wrapped = _(array).map(identity).at(paths); 1601 1602 assert.deepEqual(wrapped.value(), _.at(_.map(array, identity), paths)); 1603 }); 1604 }); 1605 } 1606 else { 1607 skipAssert(assert, 6); 1608 } 1609 }); 1610 1611 QUnit.test('should support shortcut fusion', function(assert) { 1612 assert.expect(8); 1613 1614 if (!isNpm) { 1615 var array = lodashStable.range(LARGE_ARRAY_SIZE), 1616 count = 0, 1617 iteratee = function(value) { count++; return square(value); }, 1618 lastIndex = LARGE_ARRAY_SIZE - 1; 1619 1620 lodashStable.each([lastIndex, lastIndex + '', LARGE_ARRAY_SIZE, []], function(n, index) { 1621 count = 0; 1622 var actual = _(array).map(iteratee).at(n).value(), 1623 expected = index < 2 ? 1 : 0; 1624 1625 assert.strictEqual(count, expected); 1626 1627 expected = index == 3 ? [] : [index == 2 ? undefined : square(lastIndex)]; 1628 assert.deepEqual(actual, expected); 1629 }); 1630 } 1631 else { 1632 skipAssert(assert, 8); 1633 } 1634 }); 1635 1636 QUnit.test('work with an object for `object` when chaining', function(assert) { 1637 assert.expect(2); 1638 1639 if (!isNpm) { 1640 var paths = ['a[0].b.c', 'a[1]'], 1641 actual = _(object).map(identity).at(paths).value(); 1642 1643 assert.deepEqual(actual, _.at(_.map(object, identity), paths)); 1644 1645 var indexObject = { '0': 1 }; 1646 actual = _(indexObject).at(0).value(); 1647 assert.deepEqual(actual, _.at(indexObject, 0)); 1648 } 1649 else { 1650 skipAssert(assert, 2); 1651 } 1652 }); 1653 }()); 1654 1655 /*--------------------------------------------------------------------------*/ 1656 1657 QUnit.module('lodash.attempt'); 1658 1659 (function() { 1660 QUnit.test('should return the result of `func`', function(assert) { 1661 assert.expect(1); 1662 1663 assert.strictEqual(_.attempt(lodashStable.constant('x')), 'x'); 1664 }); 1665 1666 QUnit.test('should provide additional arguments to `func`', function(assert) { 1667 assert.expect(1); 1668 1669 var actual = _.attempt(function() { return slice.call(arguments); }, 1, 2); 1670 assert.deepEqual(actual, [1, 2]); 1671 }); 1672 1673 QUnit.test('should return the caught error', function(assert) { 1674 assert.expect(1); 1675 1676 var expected = lodashStable.map(errors, stubTrue); 1677 1678 var actual = lodashStable.map(errors, function(error) { 1679 return _.attempt(function() { throw error; }) === error; 1680 }); 1681 1682 assert.deepEqual(actual, expected); 1683 }); 1684 1685 QUnit.test('should coerce errors to error objects', function(assert) { 1686 assert.expect(1); 1687 1688 var actual = _.attempt(function() { throw 'x'; }); 1689 assert.ok(lodashStable.isEqual(actual, Error('x'))); 1690 }); 1691 1692 QUnit.test('should preserve custom errors', function(assert) { 1693 assert.expect(1); 1694 1695 var actual = _.attempt(function() { throw new CustomError('x'); }); 1696 assert.ok(actual instanceof CustomError); 1697 }); 1698 1699 QUnit.test('should work with an error object from another realm', function(assert) { 1700 assert.expect(1); 1701 1702 if (realm.errors) { 1703 var expected = lodashStable.map(realm.errors, stubTrue); 1704 1705 var actual = lodashStable.map(realm.errors, function(error) { 1706 return _.attempt(function() { throw error; }) === error; 1707 }); 1708 1709 assert.deepEqual(actual, expected); 1710 } 1711 else { 1712 skipAssert(assert); 1713 } 1714 }); 1715 1716 QUnit.test('should return an unwrapped value when implicitly chaining', function(assert) { 1717 assert.expect(1); 1718 1719 if (!isNpm) { 1720 assert.strictEqual(_(lodashStable.constant('x')).attempt(), 'x'); 1721 } 1722 else { 1723 skipAssert(assert); 1724 } 1725 }); 1726 1727 QUnit.test('should return a wrapped value when explicitly chaining', function(assert) { 1728 assert.expect(1); 1729 1730 if (!isNpm) { 1731 assert.ok(_(lodashStable.constant('x')).chain().attempt() instanceof _); 1732 } 1733 else { 1734 skipAssert(assert); 1735 } 1736 }); 1737 }()); 1738 1739 /*--------------------------------------------------------------------------*/ 1740 1741 QUnit.module('lodash.before'); 1742 1743 (function() { 1744 function before(n, times) { 1745 var count = 0; 1746 lodashStable.times(times, _.before(n, function() { count++; })); 1747 return count; 1748 } 1749 1750 QUnit.test('should create a function that invokes `func` after `n` calls', function(assert) { 1751 assert.expect(4); 1752 1753 assert.strictEqual(before(5, 4), 4, 'before(n) should invoke `func` before being called `n` times'); 1754 assert.strictEqual(before(5, 6), 4, 'before(n) should not invoke `func` after being called `n - 1` times'); 1755 assert.strictEqual(before(0, 0), 0, 'before(0) should not invoke `func` immediately'); 1756 assert.strictEqual(before(0, 1), 0, 'before(0) should not invoke `func` when called'); 1757 }); 1758 1759 QUnit.test('should coerce `n` values of `NaN` to `0`', function(assert) { 1760 assert.expect(1); 1761 1762 assert.strictEqual(before(NaN, 1), 0); 1763 }); 1764 1765 QUnit.test('should use `this` binding of function', function(assert) { 1766 assert.expect(2); 1767 1768 var before = _.before(2, function(assert) { return ++this.count; }), 1769 object = { 'before': before, 'count': 0 }; 1770 1771 object.before(); 1772 assert.strictEqual(object.before(), 1); 1773 assert.strictEqual(object.count, 1); 1774 }); 1775 }()); 1776 1777 /*--------------------------------------------------------------------------*/ 1778 1779 QUnit.module('lodash.bind'); 1780 1781 (function() { 1782 function fn() { 1783 var result = [this]; 1784 push.apply(result, arguments); 1785 return result; 1786 } 1787 1788 QUnit.test('should bind a function to an object', function(assert) { 1789 assert.expect(1); 1790 1791 var object = {}, 1792 bound = _.bind(fn, object); 1793 1794 assert.deepEqual(bound('a'), [object, 'a']); 1795 }); 1796 1797 QUnit.test('should accept a falsey `thisArg`', function(assert) { 1798 assert.expect(1); 1799 1800 var values = lodashStable.reject(falsey.slice(1), function(value) { return value == null; }), 1801 expected = lodashStable.map(values, function(value) { return [value]; }); 1802 1803 var actual = lodashStable.map(values, function(value) { 1804 try { 1805 var bound = _.bind(fn, value); 1806 return bound(); 1807 } catch (e) {} 1808 }); 1809 1810 assert.ok(lodashStable.every(actual, function(value, index) { 1811 return lodashStable.isEqual(value, expected[index]); 1812 })); 1813 }); 1814 1815 QUnit.test('should bind a function to nullish values', function(assert) { 1816 assert.expect(6); 1817 1818 var bound = _.bind(fn, null), 1819 actual = bound('a'); 1820 1821 assert.ok((actual[0] === null) || (actual[0] && actual[0].Array)); 1822 assert.strictEqual(actual[1], 'a'); 1823 1824 lodashStable.times(2, function(index) { 1825 bound = index ? _.bind(fn, undefined) : _.bind(fn); 1826 actual = bound('b'); 1827 1828 assert.ok((actual[0] === undefined) || (actual[0] && actual[0].Array)); 1829 assert.strictEqual(actual[1], 'b'); 1830 }); 1831 }); 1832 1833 QUnit.test('should partially apply arguments ', function(assert) { 1834 assert.expect(4); 1835 1836 var object = {}, 1837 bound = _.bind(fn, object, 'a'); 1838 1839 assert.deepEqual(bound(), [object, 'a']); 1840 1841 bound = _.bind(fn, object, 'a'); 1842 assert.deepEqual(bound('b'), [object, 'a', 'b']); 1843 1844 bound = _.bind(fn, object, 'a', 'b'); 1845 assert.deepEqual(bound(), [object, 'a', 'b']); 1846 assert.deepEqual(bound('c', 'd'), [object, 'a', 'b', 'c', 'd']); 1847 }); 1848 1849 QUnit.test('should support placeholders', function(assert) { 1850 assert.expect(4); 1851 1852 var object = {}, 1853 ph = _.bind.placeholder, 1854 bound = _.bind(fn, object, ph, 'b', ph); 1855 1856 assert.deepEqual(bound('a', 'c'), [object, 'a', 'b', 'c']); 1857 assert.deepEqual(bound('a'), [object, 'a', 'b', undefined]); 1858 assert.deepEqual(bound('a', 'c', 'd'), [object, 'a', 'b', 'c', 'd']); 1859 assert.deepEqual(bound(), [object, undefined, 'b', undefined]); 1860 }); 1861 1862 QUnit.test('should use `_.placeholder` when set', function(assert) { 1863 assert.expect(1); 1864 1865 if (!isModularize) { 1866 var _ph = _.placeholder = {}, 1867 ph = _.bind.placeholder, 1868 object = {}, 1869 bound = _.bind(fn, object, _ph, 'b', ph); 1870 1871 assert.deepEqual(bound('a', 'c'), [object, 'a', 'b', ph, 'c']); 1872 delete _.placeholder; 1873 } 1874 else { 1875 skipAssert(assert); 1876 } 1877 }); 1878 1879 QUnit.test('should create a function with a `length` of `0`', function(assert) { 1880 assert.expect(2); 1881 1882 var fn = function(a, b, c) {}, 1883 bound = _.bind(fn, {}); 1884 1885 assert.strictEqual(bound.length, 0); 1886 1887 bound = _.bind(fn, {}, 1); 1888 assert.strictEqual(bound.length, 0); 1889 }); 1890 1891 QUnit.test('should ignore binding when called with the `new` operator', function(assert) { 1892 assert.expect(3); 1893 1894 function Foo() { 1895 return this; 1896 } 1897 1898 var bound = _.bind(Foo, { 'a': 1 }), 1899 newBound = new bound; 1900 1901 assert.strictEqual(bound().a, 1); 1902 assert.strictEqual(newBound.a, undefined); 1903 assert.ok(newBound instanceof Foo); 1904 }); 1905 1906 QUnit.test('should handle a number of arguments when called with the `new` operator', function(assert) { 1907 assert.expect(1); 1908 1909 function Foo() { 1910 return this; 1911 } 1912 1913 function Bar() {} 1914 1915 var thisArg = { 'a': 1 }, 1916 boundFoo = _.bind(Foo, thisArg), 1917 boundBar = _.bind(Bar, thisArg), 1918 count = 9, 1919 expected = lodashStable.times(count, lodashStable.constant([undefined, undefined])); 1920 1921 var actual = lodashStable.times(count, function(index) { 1922 try { 1923 switch (index) { 1924 case 0: return [new boundFoo().a, new boundBar().a]; 1925 case 1: return [new boundFoo(1).a, new boundBar(1).a]; 1926 case 2: return [new boundFoo(1, 2).a, new boundBar(1, 2).a]; 1927 case 3: return [new boundFoo(1, 2, 3).a, new boundBar(1, 2, 3).a]; 1928 case 4: return [new boundFoo(1, 2, 3, 4).a, new boundBar(1, 2, 3, 4).a]; 1929 case 5: return [new boundFoo(1, 2, 3, 4, 5).a, new boundBar(1, 2, 3, 4, 5).a]; 1930 case 6: return [new boundFoo(1, 2, 3, 4, 5, 6).a, new boundBar(1, 2, 3, 4, 5, 6).a]; 1931 case 7: return [new boundFoo(1, 2, 3, 4, 5, 6, 7).a, new boundBar(1, 2, 3, 4, 5, 6, 7).a]; 1932 case 8: return [new boundFoo(1, 2, 3, 4, 5, 6, 7, 8).a, new boundBar(1, 2, 3, 4, 5, 6, 7, 8).a]; 1933 } 1934 } catch (e) {} 1935 }); 1936 1937 assert.deepEqual(actual, expected); 1938 }); 1939 1940 QUnit.test('should ensure `new bound` is an instance of `func`', function(assert) { 1941 assert.expect(2); 1942 1943 function Foo(value) { 1944 return value && object; 1945 } 1946 1947 var bound = _.bind(Foo), 1948 object = {}; 1949 1950 assert.ok(new bound instanceof Foo); 1951 assert.strictEqual(new bound(true), object); 1952 }); 1953 1954 QUnit.test('should append array arguments to partially applied arguments', function(assert) { 1955 assert.expect(1); 1956 1957 var object = {}, 1958 bound = _.bind(fn, object, 'a'); 1959 1960 assert.deepEqual(bound(['b'], 'c'), [object, 'a', ['b'], 'c']); 1961 }); 1962 1963 QUnit.test('should not rebind functions', function(assert) { 1964 assert.expect(3); 1965 1966 var object1 = {}, 1967 object2 = {}, 1968 object3 = {}; 1969 1970 var bound1 = _.bind(fn, object1), 1971 bound2 = _.bind(bound1, object2, 'a'), 1972 bound3 = _.bind(bound1, object3, 'b'); 1973 1974 assert.deepEqual(bound1(), [object1]); 1975 assert.deepEqual(bound2(), [object1, 'a']); 1976 assert.deepEqual(bound3(), [object1, 'b']); 1977 }); 1978 1979 QUnit.test('should not error when instantiating bound built-ins', function(assert) { 1980 assert.expect(2); 1981 1982 var Ctor = _.bind(Date, null), 1983 expected = new Date(2012, 4, 23, 0, 0, 0, 0); 1984 1985 try { 1986 var actual = new Ctor(2012, 4, 23, 0, 0, 0, 0); 1987 } catch (e) {} 1988 1989 assert.deepEqual(actual, expected); 1990 1991 Ctor = _.bind(Date, null, 2012, 4, 23); 1992 1993 try { 1994 actual = new Ctor(0, 0, 0, 0); 1995 } catch (e) {} 1996 1997 assert.deepEqual(actual, expected); 1998 }); 1999 2000 QUnit.test('should not error when calling bound class constructors with the `new` operator', function(assert) { 2001 assert.expect(1); 2002 2003 var createCtor = lodashStable.attempt(Function, '"use strict";return class A{}'); 2004 2005 if (typeof createCtor == 'function') { 2006 var bound = _.bind(createCtor()), 2007 count = 8, 2008 expected = lodashStable.times(count, stubTrue); 2009 2010 var actual = lodashStable.times(count, function(index) { 2011 try { 2012 switch (index) { 2013 case 0: return !!(new bound); 2014 case 1: return !!(new bound(1)); 2015 case 2: return !!(new bound(1, 2)); 2016 case 3: return !!(new bound(1, 2, 3)); 2017 case 4: return !!(new bound(1, 2, 3, 4)); 2018 case 5: return !!(new bound(1, 2, 3, 4, 5)); 2019 case 6: return !!(new bound(1, 2, 3, 4, 5, 6)); 2020 case 7: return !!(new bound(1, 2, 3, 4, 5, 6, 7)); 2021 } 2022 } catch (e) {} 2023 }); 2024 2025 assert.deepEqual(actual, expected); 2026 } 2027 else { 2028 skipAssert(assert); 2029 } 2030 }); 2031 2032 QUnit.test('should return a wrapped value when chaining', function(assert) { 2033 assert.expect(2); 2034 2035 if (!isNpm) { 2036 var object = {}, 2037 bound = _(fn).bind({}, 'a', 'b'); 2038 2039 assert.ok(bound instanceof _); 2040 2041 var actual = bound.value()('c'); 2042 assert.deepEqual(actual, [object, 'a', 'b', 'c']); 2043 } 2044 else { 2045 skipAssert(assert, 2); 2046 } 2047 }); 2048 }()); 2049 2050 /*--------------------------------------------------------------------------*/ 2051 2052 QUnit.module('lodash.bindAll'); 2053 2054 (function() { 2055 var args = toArgs(['a']); 2056 2057 var source = { 2058 '_n0': -2, 2059 '_p0': -1, 2060 '_a': 1, 2061 '_b': 2, 2062 '_c': 3, 2063 '_d': 4, 2064 '-0': function() { return this._n0; }, 2065 '0': function() { return this._p0; }, 2066 'a': function() { return this._a; }, 2067 'b': function() { return this._b; }, 2068 'c': function() { return this._c; }, 2069 'd': function() { return this._d; } 2070 }; 2071 2072 QUnit.test('should accept individual method names', function(assert) { 2073 assert.expect(1); 2074 2075 var object = lodashStable.cloneDeep(source); 2076 _.bindAll(object, 'a', 'b'); 2077 2078 var actual = lodashStable.map(['a', 'b', 'c'], function(key) { 2079 return object[key].call({}); 2080 }); 2081 2082 assert.deepEqual(actual, [1, 2, undefined]); 2083 }); 2084 2085 QUnit.test('should accept arrays of method names', function(assert) { 2086 assert.expect(1); 2087 2088 var object = lodashStable.cloneDeep(source); 2089 _.bindAll(object, ['a', 'b'], ['c']); 2090 2091 var actual = lodashStable.map(['a', 'b', 'c', 'd'], function(key) { 2092 return object[key].call({}); 2093 }); 2094 2095 assert.deepEqual(actual, [1, 2, 3, undefined]); 2096 }); 2097 2098 QUnit.test('should preserve the sign of `0`', function(assert) { 2099 assert.expect(1); 2100 2101 var props = [-0, Object(-0), 0, Object(0)]; 2102 2103 var actual = lodashStable.map(props, function(key) { 2104 var object = lodashStable.cloneDeep(source); 2105 _.bindAll(object, key); 2106 return object[lodashStable.toString(key)].call({}); 2107 }); 2108 2109 assert.deepEqual(actual, [-2, -2, -1, -1]); 2110 }); 2111 2112 QUnit.test('should work with an array `object`', function(assert) { 2113 assert.expect(1); 2114 2115 var array = ['push', 'pop']; 2116 _.bindAll(array); 2117 assert.strictEqual(array.pop, arrayProto.pop); 2118 }); 2119 2120 QUnit.test('should work with `arguments` objects as secondary arguments', function(assert) { 2121 assert.expect(1); 2122 2123 var object = lodashStable.cloneDeep(source); 2124 _.bindAll(object, args); 2125 2126 var actual = lodashStable.map(args, function(key) { 2127 return object[key].call({}); 2128 }); 2129 2130 assert.deepEqual(actual, [1]); 2131 }); 2132 }()); 2133 2134 /*--------------------------------------------------------------------------*/ 2135 2136 QUnit.module('lodash.bindKey'); 2137 2138 (function() { 2139 QUnit.test('should work when the target function is overwritten', function(assert) { 2140 assert.expect(2); 2141 2142 var object = { 2143 'user': 'fred', 2144 'greet': function(greeting) { 2145 return this.user + ' says: ' + greeting; 2146 } 2147 }; 2148 2149 var bound = _.bindKey(object, 'greet', 'hi'); 2150 assert.strictEqual(bound(), 'fred says: hi'); 2151 2152 object.greet = function(greeting) { 2153 return this.user + ' says: ' + greeting + '!'; 2154 }; 2155 2156 assert.strictEqual(bound(), 'fred says: hi!'); 2157 }); 2158 2159 QUnit.test('should support placeholders', function(assert) { 2160 assert.expect(4); 2161 2162 var object = { 2163 'fn': function() { 2164 return slice.call(arguments); 2165 } 2166 }; 2167 2168 var ph = _.bindKey.placeholder, 2169 bound = _.bindKey(object, 'fn', ph, 'b', ph); 2170 2171 assert.deepEqual(bound('a', 'c'), ['a', 'b', 'c']); 2172 assert.deepEqual(bound('a'), ['a', 'b', undefined]); 2173 assert.deepEqual(bound('a', 'c', 'd'), ['a', 'b', 'c', 'd']); 2174 assert.deepEqual(bound(), [undefined, 'b', undefined]); 2175 }); 2176 2177 QUnit.test('should use `_.placeholder` when set', function(assert) { 2178 assert.expect(1); 2179 2180 if (!isModularize) { 2181 var object = { 2182 'fn': function() { 2183 return slice.call(arguments); 2184 } 2185 }; 2186 2187 var _ph = _.placeholder = {}, 2188 ph = _.bindKey.placeholder, 2189 bound = _.bindKey(object, 'fn', _ph, 'b', ph); 2190 2191 assert.deepEqual(bound('a', 'c'), ['a', 'b', ph, 'c']); 2192 delete _.placeholder; 2193 } 2194 else { 2195 skipAssert(assert); 2196 } 2197 }); 2198 2199 QUnit.test('should ensure `new bound` is an instance of `object[key]`', function(assert) { 2200 assert.expect(2); 2201 2202 function Foo(value) { 2203 return value && object; 2204 } 2205 2206 var object = { 'Foo': Foo }, 2207 bound = _.bindKey(object, 'Foo'); 2208 2209 assert.ok(new bound instanceof Foo); 2210 assert.strictEqual(new bound(true), object); 2211 }); 2212 }()); 2213 2214 /*--------------------------------------------------------------------------*/ 2215 2216 QUnit.module('case methods'); 2217 2218 lodashStable.each(['camel', 'kebab', 'lower', 'snake', 'start', 'upper'], function(caseName) { 2219 var methodName = caseName + 'Case', 2220 func = _[methodName]; 2221 2222 var strings = [ 2223 'foo bar', 'Foo bar', 'foo Bar', 'Foo Bar', 2224 'FOO BAR', 'fooBar', '--foo-bar--', '__foo_bar__' 2225 ]; 2226 2227 var converted = (function() { 2228 switch (caseName) { 2229 case 'camel': return 'fooBar'; 2230 case 'kebab': return 'foo-bar'; 2231 case 'lower': return 'foo bar'; 2232 case 'snake': return 'foo_bar'; 2233 case 'start': return 'Foo Bar'; 2234 case 'upper': return 'FOO BAR'; 2235 } 2236 }()); 2237 2238 QUnit.test('`_.' + methodName + '` should convert `string` to ' + caseName + ' case', function(assert) { 2239 assert.expect(1); 2240 2241 var actual = lodashStable.map(strings, function(string) { 2242 var expected = (caseName == 'start' && string == 'FOO BAR') ? string : converted; 2243 return func(string) === expected; 2244 }); 2245 2246 assert.deepEqual(actual, lodashStable.map(strings, stubTrue)); 2247 }); 2248 2249 QUnit.test('`_.' + methodName + '` should handle double-converting strings', function(assert) { 2250 assert.expect(1); 2251 2252 var actual = lodashStable.map(strings, function(string) { 2253 var expected = (caseName == 'start' && string == 'FOO BAR') ? string : converted; 2254 return func(func(string)) === expected; 2255 }); 2256 2257 assert.deepEqual(actual, lodashStable.map(strings, stubTrue)); 2258 }); 2259 2260 QUnit.test('`_.' + methodName + '` should deburr letters', function(assert) { 2261 assert.expect(1); 2262 2263 var actual = lodashStable.map(burredLetters, function(burred, index) { 2264 var letter = deburredLetters[index].replace(/['\u2019]/g, ''); 2265 if (caseName == 'start') { 2266 letter = letter == 'IJ' ? letter : lodashStable.capitalize(letter); 2267 } else if (caseName == 'upper') { 2268 letter = letter.toUpperCase(); 2269 } else { 2270 letter = letter.toLowerCase(); 2271 } 2272 return func(burred) === letter; 2273 }); 2274 2275 assert.deepEqual(actual, lodashStable.map(burredLetters, stubTrue)); 2276 }); 2277 2278 QUnit.test('`_.' + methodName + '` should remove contraction apostrophes', function(assert) { 2279 assert.expect(2); 2280 2281 var postfixes = ['d', 'll', 'm', 're', 's', 't', 've']; 2282 2283 lodashStable.each(["'", '\u2019'], function(apos) { 2284 var actual = lodashStable.map(postfixes, function(postfix) { 2285 return func('a b' + apos + postfix + ' c'); 2286 }); 2287 2288 var expected = lodashStable.map(postfixes, function(postfix) { 2289 switch (caseName) { 2290 case 'camel': return 'aB' + postfix + 'C'; 2291 case 'kebab': return 'a-b' + postfix + '-c'; 2292 case 'lower': return 'a b' + postfix + ' c'; 2293 case 'snake': return 'a_b' + postfix + '_c'; 2294 case 'start': return 'A B' + postfix + ' C'; 2295 case 'upper': return 'A B' + postfix.toUpperCase() + ' C'; 2296 } 2297 }); 2298 2299 assert.deepEqual(actual, expected); 2300 }); 2301 }); 2302 2303 QUnit.test('`_.' + methodName + '` should remove Latin mathematical operators', function(assert) { 2304 assert.expect(1); 2305 2306 var actual = lodashStable.map(['\xd7', '\xf7'], func); 2307 assert.deepEqual(actual, ['', '']); 2308 }); 2309 2310 QUnit.test('`_.' + methodName + '` should coerce `string` to a string', function(assert) { 2311 assert.expect(2); 2312 2313 var string = 'foo bar'; 2314 assert.strictEqual(func(Object(string)), converted); 2315 assert.strictEqual(func({ 'toString': lodashStable.constant(string) }), converted); 2316 }); 2317 2318 QUnit.test('`_.' + methodName + '` should return an unwrapped value implicitly when chaining', function(assert) { 2319 assert.expect(1); 2320 2321 if (!isNpm) { 2322 assert.strictEqual(_('foo bar')[methodName](), converted); 2323 } 2324 else { 2325 skipAssert(assert); 2326 } 2327 }); 2328 2329 QUnit.test('`_.' + methodName + '` should return a wrapped value when explicitly chaining', function(assert) { 2330 assert.expect(1); 2331 2332 if (!isNpm) { 2333 assert.ok(_('foo bar').chain()[methodName]() instanceof _); 2334 } 2335 else { 2336 skipAssert(assert); 2337 } 2338 }); 2339 }); 2340 2341 (function() { 2342 QUnit.test('should get the original value after cycling through all case methods', function(assert) { 2343 assert.expect(1); 2344 2345 var funcs = [_.camelCase, _.kebabCase, _.lowerCase, _.snakeCase, _.startCase, _.lowerCase, _.camelCase]; 2346 2347 var actual = lodashStable.reduce(funcs, function(result, func) { 2348 return func(result); 2349 }, 'enable 6h format'); 2350 2351 assert.strictEqual(actual, 'enable6HFormat'); 2352 }); 2353 }()); 2354 2355 /*--------------------------------------------------------------------------*/ 2356 2357 QUnit.module('lodash.camelCase'); 2358 2359 (function() { 2360 QUnit.test('should work with numbers', function(assert) { 2361 assert.expect(6); 2362 2363 assert.strictEqual(_.camelCase('12 feet'), '12Feet'); 2364 assert.strictEqual(_.camelCase('enable 6h format'), 'enable6HFormat'); 2365 assert.strictEqual(_.camelCase('enable 24H format'), 'enable24HFormat'); 2366 assert.strictEqual(_.camelCase('too legit 2 quit'), 'tooLegit2Quit'); 2367 assert.strictEqual(_.camelCase('walk 500 miles'), 'walk500Miles'); 2368 assert.strictEqual(_.camelCase('xhr2 request'), 'xhr2Request'); 2369 }); 2370 2371 QUnit.test('should handle acronyms', function(assert) { 2372 assert.expect(6); 2373 2374 lodashStable.each(['safe HTML', 'safeHTML'], function(string) { 2375 assert.strictEqual(_.camelCase(string), 'safeHtml'); 2376 }); 2377 2378 lodashStable.each(['escape HTML entities', 'escapeHTMLEntities'], function(string) { 2379 assert.strictEqual(_.camelCase(string), 'escapeHtmlEntities'); 2380 }); 2381 2382 lodashStable.each(['XMLHttpRequest', 'XmlHTTPRequest'], function(string) { 2383 assert.strictEqual(_.camelCase(string), 'xmlHttpRequest'); 2384 }); 2385 }); 2386 }()); 2387 2388 /*--------------------------------------------------------------------------*/ 2389 2390 QUnit.module('lodash.capitalize'); 2391 2392 (function() { 2393 QUnit.test('should capitalize the first character of a string', function(assert) { 2394 assert.expect(3); 2395 2396 assert.strictEqual(_.capitalize('fred'), 'Fred'); 2397 assert.strictEqual(_.capitalize('Fred'), 'Fred'); 2398 assert.strictEqual(_.capitalize(' fred'), ' fred'); 2399 }); 2400 }()); 2401 2402 /*--------------------------------------------------------------------------*/ 2403 2404 QUnit.module('lodash.castArray'); 2405 2406 (function() { 2407 QUnit.test('should wrap non-array items in an array', function(assert) { 2408 assert.expect(1); 2409 2410 var values = falsey.concat(true, 1, 'a', { 'a': 1 }), 2411 expected = lodashStable.map(values, function(value) { return [value]; }), 2412 actual = lodashStable.map(values, _.castArray); 2413 2414 assert.deepEqual(actual, expected); 2415 }); 2416 2417 QUnit.test('should return array values by reference', function(assert) { 2418 assert.expect(1); 2419 2420 var array = [1]; 2421 assert.strictEqual(_.castArray(array), array); 2422 }); 2423 2424 QUnit.test('should return an empty array when no arguments are given', function(assert) { 2425 assert.expect(1); 2426 2427 assert.deepEqual(_.castArray(), []); 2428 }); 2429 }()); 2430 2431 /*--------------------------------------------------------------------------*/ 2432 2433 QUnit.module('lodash.chain'); 2434 2435 (function() { 2436 QUnit.test('should return a wrapped value', function(assert) { 2437 assert.expect(1); 2438 2439 if (!isNpm) { 2440 var actual = _.chain({ 'a': 0 }); 2441 assert.ok(actual instanceof _); 2442 } 2443 else { 2444 skipAssert(assert); 2445 } 2446 }); 2447 2448 QUnit.test('should return existing wrapped values', function(assert) { 2449 assert.expect(2); 2450 2451 if (!isNpm) { 2452 var wrapped = _({ 'a': 0 }); 2453 assert.strictEqual(_.chain(wrapped), wrapped); 2454 assert.strictEqual(wrapped.chain(), wrapped); 2455 } 2456 else { 2457 skipAssert(assert, 2); 2458 } 2459 }); 2460 2461 QUnit.test('should enable chaining for methods that return unwrapped values', function(assert) { 2462 assert.expect(6); 2463 2464 if (!isNpm) { 2465 var array = ['c', 'b', 'a']; 2466 2467 assert.ok(_.chain(array).head() instanceof _); 2468 assert.ok(_(array).chain().head() instanceof _); 2469 2470 assert.ok(_.chain(array).isArray() instanceof _); 2471 assert.ok(_(array).chain().isArray() instanceof _); 2472 2473 assert.ok(_.chain(array).sortBy().head() instanceof _); 2474 assert.ok(_(array).chain().sortBy().head() instanceof _); 2475 } 2476 else { 2477 skipAssert(assert, 6); 2478 } 2479 }); 2480 2481 QUnit.test('should chain multiple methods', function(assert) { 2482 assert.expect(6); 2483 2484 if (!isNpm) { 2485 lodashStable.times(2, function(index) { 2486 var array = ['one two three four', 'five six seven eight', 'nine ten eleven twelve'], 2487 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 }, 2488 wrapped = index ? _(array).chain() : _.chain(array); 2489 2490 var actual = wrapped 2491 .chain() 2492 .map(function(value) { return value.split(''); }) 2493 .flatten() 2494 .reduce(function(object, chr) { 2495 object[chr] || (object[chr] = 0); 2496 object[chr]++; 2497 return object; 2498 }, {}) 2499 .value(); 2500 2501 assert.deepEqual(actual, expected); 2502 2503 array = [1, 2, 3, 4, 5, 6]; 2504 wrapped = index ? _(array).chain() : _.chain(array); 2505 actual = wrapped 2506 .chain() 2507 .filter(function(n) { return n % 2 != 0; }) 2508 .reject(function(n) { return n % 3 == 0; }) 2509 .sortBy(function(n) { return -n; }) 2510 .value(); 2511 2512 assert.deepEqual(actual, [5, 1]); 2513 2514 array = [3, 4]; 2515 wrapped = index ? _(array).chain() : _.chain(array); 2516 actual = wrapped 2517 .reverse() 2518 .concat([2, 1]) 2519 .unshift(5) 2520 .tap(function(value) { value.pop(); }) 2521 .map(square) 2522 .value(); 2523 2524 assert.deepEqual(actual, [25, 16, 9, 4]); 2525 }); 2526 } 2527 else { 2528 skipAssert(assert, 6); 2529 } 2530 }); 2531 }()); 2532 2533 /*--------------------------------------------------------------------------*/ 2534 2535 QUnit.module('lodash.chunk'); 2536 2537 (function() { 2538 var array = [0, 1, 2, 3, 4, 5]; 2539 2540 QUnit.test('should return chunked arrays', function(assert) { 2541 assert.expect(1); 2542 2543 var actual = _.chunk(array, 3); 2544 assert.deepEqual(actual, [[0, 1, 2], [3, 4, 5]]); 2545 }); 2546 2547 QUnit.test('should return the last chunk as remaining elements', function(assert) { 2548 assert.expect(1); 2549 2550 var actual = _.chunk(array, 4); 2551 assert.deepEqual(actual, [[0, 1, 2, 3], [4, 5]]); 2552 }); 2553 2554 QUnit.test('should treat falsey `size` values, except `undefined`, as `0`', function(assert) { 2555 assert.expect(1); 2556 2557 var expected = lodashStable.map(falsey, function(value) { 2558 return value === undefined ? [[0], [1], [2], [3], [4], [5]] : []; 2559 }); 2560 2561 var actual = lodashStable.map(falsey, function(size, index) { 2562 return index ? _.chunk(array, size) : _.chunk(array); 2563 }); 2564 2565 assert.deepEqual(actual, expected); 2566 }); 2567 2568 QUnit.test('should ensure the minimum `size` is `0`', function(assert) { 2569 assert.expect(1); 2570 2571 var values = lodashStable.reject(falsey, lodashStable.isUndefined).concat(-1, -Infinity), 2572 expected = lodashStable.map(values, stubArray); 2573 2574 var actual = lodashStable.map(values, function(n) { 2575 return _.chunk(array, n); 2576 }); 2577 2578 assert.deepEqual(actual, expected); 2579 }); 2580 2581 QUnit.test('should coerce `size` to an integer', function(assert) { 2582 assert.expect(1); 2583 2584 assert.deepEqual(_.chunk(array, array.length / 4), [[0], [1], [2], [3], [4], [5]]); 2585 }); 2586 2587 QUnit.test('should work as an iteratee for methods like `_.map`', function(assert) { 2588 assert.expect(1); 2589 2590 var actual = lodashStable.map([[1, 2], [3, 4]], _.chunk); 2591 assert.deepEqual(actual, [[[1], [2]], [[3], [4]]]); 2592 }); 2593 }()); 2594 2595 /*--------------------------------------------------------------------------*/ 2596 2597 QUnit.module('lodash.clamp'); 2598 2599 (function() { 2600 QUnit.test('should work with a `max`', function(assert) { 2601 assert.expect(2); 2602 2603 assert.strictEqual(_.clamp(5, 3), 3); 2604 assert.strictEqual(_.clamp(1, 3), 1); 2605 }); 2606 2607 QUnit.test('should clamp negative numbers', function(assert) { 2608 assert.expect(3); 2609 2610 assert.strictEqual(_.clamp(-10, -5, 5), -5); 2611 assert.strictEqual(_.clamp(-10.2, -5.5, 5.5), -5.5); 2612 assert.strictEqual(_.clamp(-Infinity, -5, 5), -5); 2613 }); 2614 2615 QUnit.test('should clamp positive numbers', function(assert) { 2616 assert.expect(3); 2617 2618 assert.strictEqual(_.clamp(10, -5, 5), 5); 2619 assert.strictEqual(_.clamp(10.6, -5.6, 5.4), 5.4); 2620 assert.strictEqual(_.clamp(Infinity, -5, 5), 5); 2621 }); 2622 2623 QUnit.test('should not alter negative numbers in range', function(assert) { 2624 assert.expect(3); 2625 2626 assert.strictEqual(_.clamp(-4, -5, 5), -4); 2627 assert.strictEqual(_.clamp(-5, -5, 5), -5); 2628 assert.strictEqual(_.clamp(-5.5, -5.6, 5.6), -5.5); 2629 }); 2630 2631 QUnit.test('should not alter positive numbers in range', function(assert) { 2632 assert.expect(3); 2633 2634 assert.strictEqual(_.clamp(4, -5, 5), 4); 2635 assert.strictEqual(_.clamp(5, -5, 5), 5); 2636 assert.strictEqual(_.clamp(4.5, -5.1, 5.2), 4.5); 2637 }); 2638 2639 QUnit.test('should not alter `0` in range', function(assert) { 2640 assert.expect(1); 2641 2642 assert.strictEqual(1 / _.clamp(0, -5, 5), Infinity); 2643 }); 2644 2645 QUnit.test('should clamp to `0`', function(assert) { 2646 assert.expect(1); 2647 2648 assert.strictEqual(1 / _.clamp(-10, 0, 5), Infinity); 2649 }); 2650 2651 QUnit.test('should not alter `-0` in range', function(assert) { 2652 assert.expect(1); 2653 2654 assert.strictEqual(1 / _.clamp(-0, -5, 5), -Infinity); 2655 }); 2656 2657 QUnit.test('should clamp to `-0`', function(assert) { 2658 assert.expect(1); 2659 2660 assert.strictEqual(1 / _.clamp(-10, -0, 5), -Infinity); 2661 }); 2662 2663 QUnit.test('should return `NaN` when `number` is `NaN`', function(assert) { 2664 assert.expect(1); 2665 2666 assert.deepEqual(_.clamp(NaN, -5, 5), NaN); 2667 }); 2668 2669 QUnit.test('should coerce `min` and `max` of `NaN` to `0`', function(assert) { 2670 assert.expect(2); 2671 2672 assert.deepEqual(_.clamp(1, -5, NaN), 0); 2673 assert.deepEqual(_.clamp(-1, NaN, 5), 0); 2674 }); 2675 }()); 2676 2677 /*--------------------------------------------------------------------------*/ 2678 2679 QUnit.module('clone methods'); 2680 2681 (function() { 2682 function Foo() { 2683 this.a = 1; 2684 } 2685 Foo.prototype.b = 1; 2686 Foo.c = function() {}; 2687 2688 if (Map) { 2689 var map = new Map; 2690 map.set('a', 1); 2691 map.set('b', 2); 2692 } 2693 if (Set) { 2694 var set = new Set; 2695 set.add(1); 2696 set.add(2); 2697 } 2698 var objects = { 2699 '`arguments` objects': arguments, 2700 'arrays': ['a', ''], 2701 'array-like objects': { '0': 'a', 'length': 1 }, 2702 'booleans': false, 2703 'boolean objects': Object(false), 2704 'date objects': new Date, 2705 'Foo instances': new Foo, 2706 'objects': { 'a': 0, 'b': 1, 'c': 2 }, 2707 'objects with object values': { 'a': /a/, 'b': ['B'], 'c': { 'C': 1 } }, 2708 'objects from another document': realm.object || {}, 2709 'maps': map, 2710 'null values': null, 2711 'numbers': 0, 2712 'number objects': Object(0), 2713 'regexes': /a/gim, 2714 'sets': set, 2715 'strings': 'a', 2716 'string objects': Object('a'), 2717 'undefined values': undefined 2718 }; 2719 2720 objects.arrays.length = 3; 2721 2722 var uncloneable = { 2723 'DOM elements': body, 2724 'functions': Foo, 2725 'async functions': asyncFunc, 2726 'generator functions': genFunc, 2727 'the `Proxy` constructor': Proxy 2728 }; 2729 2730 lodashStable.each(errors, function(error) { 2731 uncloneable[error.name + 's'] = error; 2732 }); 2733 2734 QUnit.test('`_.clone` should perform a shallow clone', function(assert) { 2735 assert.expect(2); 2736 2737 var array = [{ 'a': 0 }, { 'b': 1 }], 2738 actual = _.clone(array); 2739 2740 assert.deepEqual(actual, array); 2741 assert.ok(actual !== array && actual[0] === array[0]); 2742 }); 2743 2744 QUnit.test('`_.cloneDeep` should deep clone objects with circular references', function(assert) { 2745 assert.expect(1); 2746 2747 var object = { 2748 'foo': { 'b': { 'c': { 'd': {} } } }, 2749 'bar': {} 2750 }; 2751 2752 object.foo.b.c.d = object; 2753 object.bar.b = object.foo.b; 2754 2755 var actual = _.cloneDeep(object); 2756 assert.ok(actual.bar.b === actual.foo.b && actual === actual.foo.b.c.d && actual !== object); 2757 }); 2758 2759 QUnit.test('`_.cloneDeep` should deep clone objects with lots of circular references', function(assert) { 2760 assert.expect(2); 2761 2762 var cyclical = {}; 2763 lodashStable.times(LARGE_ARRAY_SIZE + 1, function(index) { 2764 cyclical['v' + index] = [index ? cyclical['v' + (index - 1)] : cyclical]; 2765 }); 2766 2767 var clone = _.cloneDeep(cyclical), 2768 actual = clone['v' + LARGE_ARRAY_SIZE][0]; 2769 2770 assert.strictEqual(actual, clone['v' + (LARGE_ARRAY_SIZE - 1)]); 2771 assert.notStrictEqual(actual, cyclical['v' + (LARGE_ARRAY_SIZE - 1)]); 2772 }); 2773 2774 QUnit.test('`_.cloneDeepWith` should provide `stack` to `customizer`', function(assert) { 2775 assert.expect(1); 2776 2777 var actual; 2778 2779 _.cloneDeepWith({ 'a': 1 }, function() { 2780 actual = _.last(arguments); 2781 }); 2782 2783 assert.ok(isNpm 2784 ? actual.constructor.name == 'Stack' 2785 : actual instanceof mapCaches.Stack 2786 ); 2787 }); 2788 2789 lodashStable.each(['clone', 'cloneDeep'], function(methodName) { 2790 var func = _[methodName], 2791 isDeep = methodName == 'cloneDeep'; 2792 2793 lodashStable.forOwn(objects, function(object, kind) { 2794 QUnit.test('`_.' + methodName + '` should clone ' + kind, function(assert) { 2795 assert.expect(2); 2796 2797 var actual = func(object); 2798 assert.ok(lodashStable.isEqual(actual, object)); 2799 2800 if (lodashStable.isObject(object)) { 2801 assert.notStrictEqual(actual, object); 2802 } else { 2803 assert.strictEqual(actual, object); 2804 } 2805 }); 2806 }); 2807 2808 QUnit.test('`_.' + methodName + '` should clone array buffers', function(assert) { 2809 assert.expect(2); 2810 2811 if (ArrayBuffer) { 2812 var actual = func(arrayBuffer); 2813 assert.strictEqual(actual.byteLength, arrayBuffer.byteLength); 2814 assert.notStrictEqual(actual, arrayBuffer); 2815 } 2816 else { 2817 skipAssert(assert, 2); 2818 } 2819 }); 2820 2821 QUnit.test('`_.' + methodName + '` should clone buffers', function(assert) { 2822 assert.expect(4); 2823 2824 if (Buffer) { 2825 var buffer = new Buffer([1, 2]), 2826 actual = func(buffer); 2827 2828 assert.strictEqual(actual.byteLength, buffer.byteLength); 2829 assert.strictEqual(actual.inspect(), buffer.inspect()); 2830 assert.notStrictEqual(actual, buffer); 2831 2832 buffer[0] = 2; 2833 assert.strictEqual(actual[0], isDeep ? 2 : 1); 2834 } 2835 else { 2836 skipAssert(assert, 4); 2837 } 2838 }); 2839 2840 QUnit.test('`_.' + methodName + '` should clone `index` and `input` array properties', function(assert) { 2841 assert.expect(2); 2842 2843 var array = /c/.exec('abcde'), 2844 actual = func(array); 2845 2846 assert.strictEqual(actual.index, 2); 2847 assert.strictEqual(actual.input, 'abcde'); 2848 }); 2849 2850 QUnit.test('`_.' + methodName + '` should clone `lastIndex` regexp property', function(assert) { 2851 assert.expect(1); 2852 2853 var regexp = /c/g; 2854 regexp.exec('abcde'); 2855 2856 assert.strictEqual(func(regexp).lastIndex, 3); 2857 }); 2858 2859 QUnit.test('`_.' + methodName + '` should clone expando properties', function(assert) { 2860 assert.expect(1); 2861 2862 var values = lodashStable.map([false, true, 1, 'a'], function(value) { 2863 var object = Object(value); 2864 object.a = 1; 2865 return object; 2866 }); 2867 2868 var expected = lodashStable.map(values, stubTrue); 2869 2870 var actual = lodashStable.map(values, function(value) { 2871 return func(value).a === 1; 2872 }); 2873 2874 assert.deepEqual(actual, expected); 2875 }); 2876 2877 QUnit.test('`_.' + methodName + '` should clone prototype objects', function(assert) { 2878 assert.expect(2); 2879 2880 var actual = func(Foo.prototype); 2881 2882 assert.notOk(actual instanceof Foo); 2883 assert.deepEqual(actual, { 'b': 1 }); 2884 }); 2885 2886 QUnit.test('`_.' + methodName + '` should set the `[[Prototype]]` of a clone', function(assert) { 2887 assert.expect(1); 2888 2889 assert.ok(func(new Foo) instanceof Foo); 2890 }); 2891 2892 QUnit.test('`_.' + methodName + '` should set the `[[Prototype]]` of a clone even when the `constructor` is incorrect', function(assert) { 2893 assert.expect(1); 2894 2895 Foo.prototype.constructor = Object; 2896 assert.ok(func(new Foo) instanceof Foo); 2897 Foo.prototype.constructor = Foo; 2898 }); 2899 2900 QUnit.test('`_.' + methodName + '` should ensure `value` constructor is a function before using its `[[Prototype]]`', function(assert) { 2901 assert.expect(1); 2902 2903 Foo.prototype.constructor = null; 2904 assert.notOk(func(new Foo) instanceof Foo); 2905 Foo.prototype.constructor = Foo; 2906 }); 2907 2908 QUnit.test('`_.' + methodName + '` should clone properties that shadow those on `Object.prototype`', function(assert) { 2909 assert.expect(2); 2910 2911 var object = { 2912 'constructor': objectProto.constructor, 2913 'hasOwnProperty': objectProto.hasOwnProperty, 2914 'isPrototypeOf': objectProto.isPrototypeOf, 2915 'propertyIsEnumerable': objectProto.propertyIsEnumerable, 2916 'toLocaleString': objectProto.toLocaleString, 2917 'toString': objectProto.toString, 2918 'valueOf': objectProto.valueOf 2919 }; 2920 2921 var actual = func(object); 2922 2923 assert.deepEqual(actual, object); 2924 assert.notStrictEqual(actual, object); 2925 }); 2926 2927 QUnit.test('`_.' + methodName + '` should clone symbol properties', function(assert) { 2928 assert.expect(7); 2929 2930 function Foo() { 2931 this[symbol] = { 'c': 1 }; 2932 } 2933 2934 if (Symbol) { 2935 var symbol2 = Symbol('b'); 2936 Foo.prototype[symbol2] = 2; 2937 2938 var symbol3 = Symbol('c'); 2939 defineProperty(Foo.prototype, symbol3, { 2940 'configurable': true, 2941 'enumerable': false, 2942 'writable': true, 2943 'value': 3 2944 }); 2945 2946 var object = { 'a': { 'b': new Foo } }; 2947 object[symbol] = { 'b': 1 }; 2948 2949 var actual = func(object); 2950 if (isDeep) { 2951 assert.notStrictEqual(actual[symbol], object[symbol]); 2952 assert.notStrictEqual(actual.a, object.a); 2953 } else { 2954 assert.strictEqual(actual[symbol], object[symbol]); 2955 assert.strictEqual(actual.a, object.a); 2956 } 2957 assert.deepEqual(actual[symbol], object[symbol]); 2958 assert.deepEqual(getSymbols(actual.a.b), [symbol]); 2959 assert.deepEqual(actual.a.b[symbol], object.a.b[symbol]); 2960 assert.deepEqual(actual.a.b[symbol2], object.a.b[symbol2]); 2961 assert.deepEqual(actual.a.b[symbol3], object.a.b[symbol3]); 2962 } 2963 else { 2964 skipAssert(assert, 7); 2965 } 2966 }); 2967 2968 QUnit.test('`_.' + methodName + '` should clone symbol objects', function(assert) { 2969 assert.expect(4); 2970 2971 if (Symbol) { 2972 assert.strictEqual(func(symbol), symbol); 2973 2974 var object = Object(symbol), 2975 actual = func(object); 2976 2977 assert.strictEqual(typeof actual, 'object'); 2978 assert.strictEqual(typeof actual.valueOf(), 'symbol'); 2979 assert.notStrictEqual(actual, object); 2980 } 2981 else { 2982 skipAssert(assert, 4); 2983 } 2984 }); 2985 2986 QUnit.test('`_.' + methodName + '` should not clone symbol primitives', function(assert) { 2987 assert.expect(1); 2988 2989 if (Symbol) { 2990 assert.strictEqual(func(symbol), symbol); 2991 } 2992 else { 2993 skipAssert(assert); 2994 } 2995 }); 2996 2997 QUnit.test('`_.' + methodName + '` should not error on DOM elements', function(assert) { 2998 assert.expect(1); 2999 3000 if (document) { 3001 var element = document.createElement('div'); 3002 3003 try { 3004 assert.deepEqual(func(element), {}); 3005 } catch (e) { 3006 assert.ok(false, e.message); 3007 } 3008 } 3009 else { 3010 skipAssert(assert); 3011 } 3012 }); 3013 3014 QUnit.test('`_.' + methodName + '` should create an object from the same realm as `value`', function(assert) { 3015 assert.expect(1); 3016 3017 var props = []; 3018 3019 var objects = lodashStable.transform(_, function(result, value, key) { 3020 if (lodashStable.startsWith(key, '_') && lodashStable.isObject(value) && 3021 !lodashStable.isArguments(value) && !lodashStable.isElement(value) && 3022 !lodashStable.isFunction(value)) { 3023 props.push(lodashStable.capitalize(lodashStable.camelCase(key))); 3024 result.push(value); 3025 } 3026 }, []); 3027 3028 var expected = lodashStable.map(objects, stubTrue); 3029 3030 var actual = lodashStable.map(objects, function(object) { 3031 var Ctor = object.constructor, 3032 result = func(object); 3033 3034 return result !== object && ((result instanceof Ctor) || !(new Ctor instanceof Ctor)); 3035 }); 3036 3037 assert.deepEqual(actual, expected, props.join(', ')); 3038 }); 3039 3040 QUnit.test('`_.' + methodName + '` should perform a ' + (isDeep ? 'deep' : 'shallow') + ' clone when used as an iteratee for methods like `_.map`', function(assert) { 3041 assert.expect(2); 3042 3043 var expected = [{ 'a': [0] }, { 'b': [1] }], 3044 actual = lodashStable.map(expected, func); 3045 3046 assert.deepEqual(actual, expected); 3047 3048 if (isDeep) { 3049 assert.ok(actual[0] !== expected[0] && actual[0].a !== expected[0].a && actual[1].b !== expected[1].b); 3050 } else { 3051 assert.ok(actual[0] !== expected[0] && actual[0].a === expected[0].a && actual[1].b === expected[1].b); 3052 } 3053 }); 3054 3055 QUnit.test('`_.' + methodName + '` should return a unwrapped value when chaining', function(assert) { 3056 assert.expect(2); 3057 3058 if (!isNpm) { 3059 var object = objects.objects, 3060 actual = _(object)[methodName](); 3061 3062 assert.deepEqual(actual, object); 3063 assert.notStrictEqual(actual, object); 3064 } 3065 else { 3066 skipAssert(assert, 2); 3067 } 3068 }); 3069 3070 lodashStable.each(arrayViews, function(type) { 3071 QUnit.test('`_.' + methodName + '` should clone ' + type + ' values', function(assert) { 3072 assert.expect(10); 3073 3074 var Ctor = root[type]; 3075 3076 lodashStable.times(2, function(index) { 3077 if (Ctor) { 3078 var buffer = new ArrayBuffer(24), 3079 view = index ? new Ctor(buffer, 8, 1) : new Ctor(buffer), 3080 actual = func(view); 3081 3082 assert.deepEqual(actual, view); 3083 assert.notStrictEqual(actual, view); 3084 assert.strictEqual(actual.buffer === view.buffer, !isDeep); 3085 assert.strictEqual(actual.byteOffset, view.byteOffset); 3086 assert.strictEqual(actual.length, view.length); 3087 } 3088 else { 3089 skipAssert(assert, 5); 3090 } 3091 }); 3092 }); 3093 }); 3094 3095 lodashStable.forOwn(uncloneable, function(value, key) { 3096 QUnit.test('`_.' + methodName + '` should not clone ' + key, function(assert) { 3097 assert.expect(3); 3098 3099 if (value) { 3100 var object = { 'a': value, 'b': { 'c': value } }, 3101 actual = func(object), 3102 expected = value === Foo ? { 'c': Foo.c } : {}; 3103 3104 assert.deepEqual(actual, object); 3105 assert.notStrictEqual(actual, object); 3106 assert.deepEqual(func(value), expected); 3107 } 3108 else { 3109 skipAssert(assert, 3); 3110 } 3111 }); 3112 }); 3113 }); 3114 3115 lodashStable.each(['cloneWith', 'cloneDeepWith'], function(methodName) { 3116 var func = _[methodName], 3117 isDeep = methodName == 'cloneDeepWith'; 3118 3119 QUnit.test('`_.' + methodName + '` should provide correct `customizer` arguments', function(assert) { 3120 assert.expect(1); 3121 3122 var argsList = [], 3123 object = new Foo; 3124 3125 func(object, function() { 3126 var length = arguments.length, 3127 args = slice.call(arguments, 0, length - (length > 1 ? 1 : 0)); 3128 3129 argsList.push(args); 3130 }); 3131 3132 assert.deepEqual(argsList, isDeep ? [[object], [1, 'a', object]] : [[object]]); 3133 }); 3134 3135 QUnit.test('`_.' + methodName + '` should handle cloning when `customizer` returns `undefined`', function(assert) { 3136 assert.expect(1); 3137 3138 var actual = func({ 'a': { 'b': 'c' } }, noop); 3139 assert.deepEqual(actual, { 'a': { 'b': 'c' } }); 3140 }); 3141 3142 lodashStable.forOwn(uncloneable, function(value, key) { 3143 QUnit.test('`_.' + methodName + '` should work with a `customizer` callback and ' + key, function(assert) { 3144 assert.expect(3); 3145 3146 var customizer = function(value) { 3147 return lodashStable.isPlainObject(value) ? undefined : value; 3148 }; 3149 3150 var actual = func(value, customizer); 3151 assert.strictEqual(actual, value); 3152 3153 var object = { 'a': value, 'b': { 'c': value } }; 3154 actual = func(object, customizer); 3155 3156 assert.deepEqual(actual, object); 3157 assert.notStrictEqual(actual, object); 3158 }); 3159 }); 3160 }); 3161 }()); 3162 3163 /*--------------------------------------------------------------------------*/ 3164 3165 QUnit.module('lodash.compact'); 3166 3167 (function() { 3168 var largeArray = lodashStable.range(LARGE_ARRAY_SIZE).concat(null); 3169 3170 QUnit.test('should filter falsey values', function(assert) { 3171 assert.expect(1); 3172 3173 var array = ['0', '1', '2']; 3174 assert.deepEqual(_.compact(falsey.concat(array)), array); 3175 }); 3176 3177 QUnit.test('should work when in-between lazy operators', function(assert) { 3178 assert.expect(2); 3179 3180 if (!isNpm) { 3181 var actual = _(falsey).thru(_.slice).compact().thru(_.slice).value(); 3182 assert.deepEqual(actual, []); 3183 3184 actual = _(falsey).thru(_.slice).push(true, 1).compact().push('a').value(); 3185 assert.deepEqual(actual, [true, 1, 'a']); 3186 } 3187 else { 3188 skipAssert(assert, 2); 3189 } 3190 }); 3191 3192 QUnit.test('should work in a lazy sequence', function(assert) { 3193 assert.expect(1); 3194 3195 if (!isNpm) { 3196 var actual = _(largeArray).slice(1).compact().reverse().take().value(); 3197 assert.deepEqual(actual, _.take(_.compact(_.slice(largeArray, 1)).reverse())); 3198 } 3199 else { 3200 skipAssert(assert); 3201 } 3202 }); 3203 3204 QUnit.test('should work in a lazy sequence with a custom `_.iteratee`', function(assert) { 3205 assert.expect(1); 3206 3207 if (!isModularize) { 3208 var iteratee = _.iteratee, 3209 pass = false; 3210 3211 _.iteratee = identity; 3212 3213 try { 3214 var actual = _(largeArray).slice(1).compact().value(); 3215 pass = lodashStable.isEqual(actual, _.compact(_.slice(largeArray, 1))); 3216 } catch (e) {console.log(e);} 3217 3218 assert.ok(pass); 3219 _.iteratee = iteratee; 3220 } 3221 else { 3222 skipAssert(assert); 3223 } 3224 }); 3225 }()); 3226 3227 /*--------------------------------------------------------------------------*/ 3228 3229 QUnit.module('lodash.concat'); 3230 3231 (function() { 3232 QUnit.test('should shallow clone `array`', function(assert) { 3233 assert.expect(2); 3234 3235 var array = [1, 2, 3], 3236 actual = _.concat(array); 3237 3238 assert.deepEqual(actual, array); 3239 assert.notStrictEqual(actual, array); 3240 }); 3241 3242 QUnit.test('should concat arrays and values', function(assert) { 3243 assert.expect(2); 3244 3245 var array = [1], 3246 actual = _.concat(array, 2, [3], [[4]]); 3247 3248 assert.deepEqual(actual, [1, 2, 3, [4]]); 3249 assert.