1;(function() { 2 'use strict'; 3 4 /** Used as a safe reference for `undefined` in pre-ES5 environments. */ 5 var undefined; 6 7 /** Used as the size to cover large array optimizations. */ 8 var LARGE_ARRAY_SIZE = 200; 9 10 /** Used as a reference to the global object. */ 11 var root = (typeof global == 'object' && global) || this; 12 13 /** Used for native method references. */ 14 var arrayProto = Array.prototype; 15 16 /** Method and object shortcuts. */ 17 var phantom = root.phantom, 18 argv = root.process && process.argv, 19 document = !phantom && root.document, 20 slice = arrayProto.slice, 21 WeakMap = root.WeakMap; 22 23 /** Math helpers. */ 24 var add = function(x, y) { return x + y; }, 25 isEven = function(n) { return n % 2 == 0; }, 26 isEvenIndex = function(n, index) { return isEven(index); }, 27 square = function(n) { return n * n; }; 28 29 // Leak to avoid sporadic `noglobals` fails on Edge in Sauce Labs. 30 root.msWDfn = undefined; 31 32 /*--------------------------------------------------------------------------*/ 33 34 /** Load QUnit and extras. */ 35 var QUnit = root.QUnit || require('qunit-extras'); 36 37 /** Load stable Lodash. */ 38 var _ = root._ || require('../lodash.js'); 39 40 var convert = (function() { 41 var baseConvert = root.fp || require('../fp/_baseConvert.js'); 42 if (!root.fp) { 43 return function(name, func, options) { 44 return baseConvert(_, name, func, options); 45 }; 46 } 47 return function(name, func, options) { 48 if (typeof name == 'function') { 49 options = func; 50 func = name; 51 name = undefined; 52 } 53 return name === undefined 54 ? baseConvert(func, options) 55 : baseConvert(_.runInContext(), options)[name]; 56 }; 57 }()); 58 59 var allFalseOptions = { 60 'cap': false, 61 'curry': false, 62 'fixed': false, 63 'immutable': false, 64 'rearg': false 65 }; 66 67 var fp = root.fp 68 ? (fp = _.noConflict(), _ = root._, fp) 69 : convert(_.runInContext()); 70 71 var mapping = root.mapping || require('../fp/_mapping.js'); 72 73 /*--------------------------------------------------------------------------*/ 74 75 /** 76 * Skips a given number of tests with a passing result. 77 * 78 * @private 79 * @param {Object} assert The QUnit assert object. 80 * @param {number} [count=1] The number of tests to skip. 81 */ 82 function skipAssert(assert, count) { 83 count || (count = 1); 84 while (count--) { 85 assert.ok(true, 'test skipped'); 86 } 87 } 88 89 /*--------------------------------------------------------------------------*/ 90 91 if (argv) { 92 console.log('Running lodash/fp tests.'); 93 } 94 95 QUnit.module('convert module'); 96 97 (function() { 98 QUnit.test('should work with `name` and `func`', function(assert) { 99 assert.expect(2); 100 101 var array = [1, 2, 3, 4], 102 remove = convert('remove', _.remove), 103 actual = remove(isEven)(array); 104 105 assert.deepEqual(array, [1, 2, 3, 4]); 106 assert.deepEqual(actual, [1, 3]); 107 }); 108 109 QUnit.test('should work with `name`, `func`, and `options`', function(assert) { 110 assert.expect(3); 111 112 var array = [1, 2, 3, 4], 113 remove = convert('remove', _.remove, allFalseOptions); 114 115 var actual = remove(array, function(n, index) { 116 return isEven(index); 117 }); 118 119 assert.deepEqual(array, [2, 4]); 120 assert.deepEqual(actual, [1, 3]); 121 assert.deepEqual(remove(), []); 122 }); 123 124 QUnit.test('should work with an object', function(assert) { 125 assert.expect(2); 126 127 if (!document) { 128 var array = [1, 2, 3, 4], 129 lodash = convert({ 'remove': _.remove }), 130 actual = lodash.remove(isEven)(array); 131 132 assert.deepEqual(array, [1, 2, 3, 4]); 133 assert.deepEqual(actual, [1, 3]); 134 } 135 else { 136 skipAssert(assert, 2); 137 } 138 }); 139 140 QUnit.test('should work with an object and `options`', function(assert) { 141 assert.expect(3); 142 143 if (!document) { 144 var array = [1, 2, 3, 4], 145 lodash = convert({ 'remove': _.remove }, allFalseOptions), 146 actual = lodash.remove(array, isEvenIndex); 147 148 assert.deepEqual(array, [2, 4]); 149 assert.deepEqual(actual, [1, 3]); 150 assert.deepEqual(lodash.remove(), []); 151 } 152 else { 153 skipAssert(assert, 3); 154 } 155 }); 156 157 QUnit.test('should work with lodash and `options`', function(assert) { 158 assert.expect(3); 159 160 var array = [1, 2, 3, 4], 161 lodash = convert(_.runInContext(), allFalseOptions), 162 actual = lodash.remove(array, isEvenIndex); 163 164 assert.deepEqual(array, [2, 4]); 165 assert.deepEqual(actual, [1, 3]); 166 assert.deepEqual(lodash.remove(), []); 167 }); 168 169 QUnit.test('should work with `runInContext` and `options`', function(assert) { 170 assert.expect(3); 171 172 var array = [1, 2, 3, 4], 173 runInContext = convert('runInContext', _.runInContext, allFalseOptions), 174 lodash = runInContext(), 175 actual = lodash.remove(array, isEvenIndex); 176 177 assert.deepEqual(array, [2, 4]); 178 assert.deepEqual(actual, [1, 3]); 179 assert.deepEqual(lodash.remove(), []); 180 }); 181 182 QUnit.test('should accept a variety of options', function(assert) { 183 assert.expect(8); 184 185 var array = [1, 2, 3, 4], 186 value = _.clone(array), 187 remove = convert('remove', _.remove, { 'cap': false }), 188 actual = remove(isEvenIndex)(value); 189 190 assert.deepEqual(value, [1, 2, 3, 4]); 191 assert.deepEqual(actual, [2, 4]); 192 193 remove = convert('remove', _.remove, { 'curry': false }); 194 actual = remove(isEven); 195 196 assert.deepEqual(actual, []); 197 198 var trim = convert('trim', _.trim, { 'fixed': false }); 199 assert.strictEqual(trim('_-abc-_', '_-'), 'abc'); 200 201 value = _.clone(array); 202 remove = convert('remove', _.remove, { 'immutable': false }); 203 actual = remove(isEven)(value); 204 205 assert.deepEqual(value, [1, 3]); 206 assert.deepEqual(actual, [2, 4]); 207 208 value = _.clone(array); 209 remove = convert('remove', _.remove, { 'rearg': false }); 210 actual = remove(value)(isEven); 211 212 assert.deepEqual(value, [1, 2, 3, 4]); 213 assert.deepEqual(actual, [1, 3]); 214 }); 215 216 QUnit.test('should respect the `cap` option', function(assert) { 217 assert.expect(1); 218 219 var iteratee = convert('iteratee', _.iteratee, { 'cap': false }); 220 221 var func = iteratee(function(a, b, c) { 222 return [a, b, c]; 223 }, 3); 224 225 assert.deepEqual(func(1, 2, 3), [1, 2, 3]); 226 }); 227 228 QUnit.test('should respect the `rearg` option', function(assert) { 229 assert.expect(1); 230 231 var add = convert('add', _.add, { 'rearg': true }); 232 233 assert.strictEqual(add('2')('1'), '12'); 234 }); 235 236 QUnit.test('should add a `placeholder` property', function(assert) { 237 assert.expect(2); 238 239 if (!document) { 240 var lodash = convert({ 'add': _.add }); 241 242 assert.strictEqual(lodash.placeholder, lodash); 243 assert.strictEqual(lodash.add.placeholder, lodash); 244 } 245 else { 246 skipAssert(assert, 2); 247 } 248 }); 249 }()); 250 251 /*--------------------------------------------------------------------------*/ 252 253 QUnit.module('method.convert'); 254 255 (function() { 256 QUnit.test('should exist on unconverted methods', function(assert) { 257 assert.expect(2); 258 259 var array = [], 260 isArray = fp.isArray.convert({ 'curry': true }); 261 262 assert.strictEqual(fp.isArray(array), true); 263 assert.strictEqual(isArray()(array), true); 264 }); 265 266 QUnit.test('should convert method aliases', function(assert) { 267 assert.expect(1); 268 269 var all = fp.all.convert({ 'rearg': false }), 270 actual = all([0])(_.identity); 271 272 assert.strictEqual(actual, false); 273 }); 274 275 QUnit.test('should convert remapped methods', function(assert) { 276 assert.expect(1); 277 278 var extendAll = fp.extendAll.convert({ 'immutable': false }), 279 object = {}; 280 281 extendAll([object, { 'a': 1 }, { 'b': 2 }]); 282 assert.deepEqual(object, { 'a': 1, 'b': 2 }); 283 }); 284 }()); 285 286 /*--------------------------------------------------------------------------*/ 287 288 QUnit.module('convert methods'); 289 290 _.each(['fp.convert', 'method.convert'], function(methodName) { 291 var isFp = methodName == 'fp.convert', 292 func = isFp ? fp.convert : fp.remove.convert; 293 294 QUnit.test('`' + methodName + '` should work with an object', function(assert) { 295 assert.expect(3); 296 297 var array = [1, 2, 3, 4], 298 lodash = func(allFalseOptions), 299 remove = isFp ? lodash.remove : lodash, 300 actual = remove(array, isEvenIndex); 301 302 assert.deepEqual(array, [2, 4]); 303 assert.deepEqual(actual, [1, 3]); 304 assert.deepEqual(remove(), []); 305 }); 306 307 QUnit.test('`' + methodName + '` should extend existing configs', function(assert) { 308 assert.expect(2); 309 310 var array = [1, 2, 3, 4], 311 lodash = func({ 'cap': false }), 312 remove = (isFp ? lodash.remove : lodash).convert({ 'rearg': false }), 313 actual = remove(array)(isEvenIndex); 314 315 assert.deepEqual(array, [1, 2, 3, 4]); 316 assert.deepEqual(actual, [2, 4]); 317 }); 318 }); 319 320 /*--------------------------------------------------------------------------*/ 321 322 QUnit.module('method arity checks'); 323 324 (function() { 325 QUnit.test('should wrap methods with an arity > `1`', function(assert) { 326 assert.expect(1); 327 328 var methodNames = _.filter(_.functions(fp), function(methodName) { 329 return fp[methodName].length > 1; 330 }); 331 332 assert.deepEqual(methodNames, []); 333 }); 334 335 QUnit.test('should have >= arity of `aryMethod` designation', function(assert) { 336 assert.expect(4); 337 338 _.times(4, function(index) { 339 var aryCap = index + 1; 340 341 var methodNames = _.filter(mapping.aryMethod[aryCap], function(methodName) { 342 var key = _.get(mapping.remap, methodName, methodName), 343 arity = _[key].length; 344 345 return arity != 0 && arity < aryCap; 346 }); 347 348 assert.deepEqual(methodNames, [], '`aryMethod[' + aryCap + ']`'); 349 }); 350 }); 351 }()); 352 353 /*--------------------------------------------------------------------------*/ 354 355 QUnit.module('method aliases'); 356 357 (function() { 358 QUnit.test('should have correct aliases', function(assert) { 359 assert.expect(1); 360 361 var actual = _.transform(mapping.aliasToReal, function(result, realName, alias) { 362 result.push([alias, fp[alias] === fp[realName]]); 363 }, []); 364 365 assert.deepEqual(_.reject(actual, 1), []); 366 }); 367 }()); 368 369 /*--------------------------------------------------------------------------*/ 370 371 QUnit.module('method ary caps'); 372 373 (function() { 374 QUnit.test('should have a cap of 1', function(assert) { 375 assert.expect(1); 376 377 var funcMethods = [ 378 'curry', 'iteratee', 'memoize', 'over', 'overEvery', 'overSome', 379 'method', 'methodOf', 'rest', 'runInContext' 380 ]; 381 382 var exceptions = funcMethods.concat('mixin', 'nthArg', 'template'), 383 expected = _.map(mapping.aryMethod[1], _.constant(true)); 384 385 var actual = _.map(mapping.aryMethod[1], function(methodName) { 386 var arg = _.includes(funcMethods, methodName) ? _.noop : 1, 387 result = _.attempt(function() { return fp[methodName](arg); }); 388 389 if (_.includes(exceptions, methodName) 390 ? typeof result == 'function' 391 : typeof result != 'function' 392 ) { 393 return true; 394 } 395 console.log(methodName, result); 396 return false; 397 }); 398 399 assert.deepEqual(actual, expected); 400 }); 401 402 QUnit.test('should have a cap of 2', function(assert) { 403 assert.expect(1); 404 405 var funcMethods = [ 406 'after', 'ary', 'before', 'bind', 'bindKey', 'curryN', 'debounce', 407 'delay', 'overArgs', 'partial', 'partialRight', 'rearg', 'throttle', 408 'wrap' 409 ]; 410 411 var exceptions = _.without(funcMethods.concat('matchesProperty'), 'delay'), 412 expected = _.map(mapping.aryMethod[2], _.constant(true)); 413 414 var actual = _.map(mapping.aryMethod[2], function(methodName) { 415 var args = _.includes(funcMethods, methodName) ? [methodName == 'curryN' ? 1 : _.noop, _.noop] : [1, []], 416 result = _.attempt(function() { return fp[methodName](args[0])(args[1]); }); 417 418 if (_.includes(exceptions, methodName) 419 ? typeof result == 'function' 420 : typeof result != 'function' 421 ) { 422 return true; 423 } 424 console.log(methodName, result); 425 return false; 426 }); 427 428 assert.deepEqual(actual, expected); 429 }); 430 431 QUnit.test('should have a cap of 3', function(assert) { 432 assert.expect(1); 433 434 var funcMethods = [ 435 'assignWith', 'extendWith', 'isEqualWith', 'isMatchWith', 'reduce', 436 'reduceRight', 'transform', 'zipWith' 437 ]; 438 439 var expected = _.map(mapping.aryMethod[3], _.constant(true)); 440 441 var actual = _.map(mapping.aryMethod[3], function(methodName) { 442 var args = _.includes(funcMethods, methodName) ? [_.noop, 0, 1] : [0, 1, []], 443 result = _.attempt(function() { return fp[methodName](args[0])(args[1])(args[2]); }); 444 445 if (typeof result != 'function') { 446 return true; 447 } 448 console.log(methodName, result); 449 return false; 450 }); 451 452 assert.deepEqual(actual, expected); 453 }); 454 }()); 455 456 /*--------------------------------------------------------------------------*/ 457 458 QUnit.module('methods that use `indexOf`'); 459 460 (function() { 461 QUnit.test('should work with `fp.indexOf`', function(assert) { 462 assert.expect(10); 463 464 var array = ['a', 'b', 'c'], 465 other = ['b', 'd', 'b'], 466 object = { 'a': 1, 'b': 2, 'c': 2 }, 467 actual = fp.difference(array)(other); 468 469 assert.deepEqual(actual, ['a', 'c'], 'fp.difference'); 470 471 actual = fp.includes('b')(array); 472 assert.strictEqual(actual, true, 'fp.includes'); 473 474 actual = fp.intersection(other)(array); 475 assert.deepEqual(actual, ['b'], 'fp.intersection'); 476 477 actual = fp.omit(other)(object); 478 assert.deepEqual(actual, { 'a': 1, 'c': 2 }, 'fp.omit'); 479 480 actual = fp.union(other)(array); 481 assert.deepEqual(actual, ['a', 'b', 'c', 'd'], 'fp.union'); 482 483 actual = fp.uniq(other); 484 assert.deepEqual(actual, ['b', 'd'], 'fp.uniq'); 485 486 actual = fp.uniqBy(_.identity, other); 487 assert.deepEqual(actual, ['b', 'd'], 'fp.uniqBy'); 488 489 actual = fp.without(other)(array); 490 assert.deepEqual(actual, ['a', 'c'], 'fp.without'); 491 492 actual = fp.xor(other)(array); 493 assert.deepEqual(actual, ['a', 'c', 'd'], 'fp.xor'); 494 495 actual = fp.pull('b')(array); 496 assert.deepEqual(actual, ['a', 'c'], 'fp.pull'); 497 }); 498 }()); 499 500 /*--------------------------------------------------------------------------*/ 501 502 QUnit.module('cherry-picked methods'); 503 504 (function() { 505 QUnit.test('should provide the correct `iteratee` arguments', function(assert) { 506 assert.expect(4); 507 508 var args, 509 array = [1, 2, 3], 510 object = { 'a': 1, 'b': 2 }, 511 isFIFO = _.keys(object)[0] == 'a', 512 map = convert('map', _.map), 513 reduce = convert('reduce', _.reduce); 514 515 map(function() { 516 args || (args = slice.call(arguments)); 517 })(array); 518 519 assert.deepEqual(args, [1]); 520 521 args = undefined; 522 map(function() { 523 args || (args = slice.call(arguments)); 524 })(object); 525 526 assert.deepEqual(args, isFIFO ? [1] : [2]); 527 528 args = undefined; 529 reduce(function() { 530 args || (args = slice.call(arguments)); 531 })(0)(array); 532 533 assert.deepEqual(args, [0, 1]); 534 535 args = undefined; 536 reduce(function() { 537 args || (args = slice.call(arguments)); 538 })(0)(object); 539 540 assert.deepEqual(args, isFIFO ? [0, 1] : [0, 2]); 541 }); 542 543 QUnit.test('should not support shortcut fusion', function(assert) { 544 assert.expect(3); 545 546 var array = fp.range(0, LARGE_ARRAY_SIZE), 547 filterCount = 0, 548 mapCount = 0; 549 550 var iteratee = function(value) { 551 mapCount++; 552 return value * value; 553 }; 554 555 var predicate = function(value) { 556 filterCount++; 557 return isEven(value); 558 }; 559 560 var map1 = convert('map', _.map), 561 filter1 = convert('filter', _.filter), 562 take1 = convert('take', _.take); 563 564 var filter2 = filter1(predicate), 565 map2 = map1(iteratee), 566 take2 = take1(2); 567 568 var combined = fp.flow(map2, filter2, fp.compact, take2); 569 570 assert.deepEqual(combined(array), [4, 16]); 571 assert.strictEqual(filterCount, 200, 'filterCount'); 572 assert.strictEqual(mapCount, 200, 'mapCount'); 573 }); 574 }()); 575 576 /*--------------------------------------------------------------------------*/ 577 578 QUnit.module('iteratee shorthands'); 579 580 (function() { 581 var objects = [{ 'a': 1, 'b': 2 }, { 'a': 3, 'b': 4 }]; 582 583 QUnit.test('should work with "_.matches" shorthands', function(assert) { 584 assert.expect(1); 585 586 assert.deepEqual(fp.filter({ 'a': 3 })(objects), [objects[1]]); 587 }); 588 589 QUnit.test('should work with "_.matchesProperty" shorthands', function(assert) { 590 assert.expect(1); 591 592 assert.deepEqual(fp.filter(['a', 3])(objects), [objects[1]]); 593 }); 594 595 QUnit.test('should work with "_.property" shorthands', function(assert) { 596 assert.expect(1); 597 598 assert.deepEqual(fp.map('a')(objects), [1, 3]); 599 }); 600 }()); 601 602 /*--------------------------------------------------------------------------*/ 603 604 QUnit.module('placeholder methods'); 605 606 (function() { 607 QUnit.test('should use `fp` as the default placeholder', function(assert) { 608 assert.expect(3); 609 610 var actual = fp.add(fp, 'b')('a'); 611 assert.strictEqual(actual, 'ab'); 612 613 actual = fp.fill(fp, 2)(1, '*')([1, 2, 3]); 614 assert.deepEqual(actual, [1, '*', 3]); 615 616 actual = fp.slice(fp, 2)(1)(['a', 'b', 'c']); 617 assert.deepEqual(actual, ['b']); 618 }); 619 620 QUnit.test('should support `fp.placeholder`', function(assert) { 621 assert.expect(6); 622 623 _.each([[], fp.__], function(ph) { 624 fp.placeholder = ph; 625 626 var actual = fp.add(ph, 'b')('a'); 627 assert.strictEqual(actual, 'ab'); 628 629 actual = fp.fill(ph, 2)(1, '*')([1, 2, 3]); 630 assert.deepEqual(actual, [1, '*', 3]); 631 632 actual = fp.slice(ph, 2)(1)(['a', 'b', 'c']); 633 assert.deepEqual(actual, ['b']); 634 }); 635 }); 636 637 var methodNames = [ 638 'bind', 639 'bindKey', 640 'curry', 641 'curryRight', 642 'partial', 643 'partialRight' 644 ]; 645 646 _.each(methodNames, function(methodName) { 647 var func = fp[methodName]; 648 649 QUnit.test('fp.' + methodName + '` should have a `placeholder` property', function(assert) { 650 assert.expect(2); 651 652 assert.ok(_.isObject(func.placeholder)); 653 assert.strictEqual(func.placeholder, fp.__); 654 }); 655 }); 656 }()); 657 658 /*--------------------------------------------------------------------------*/ 659 660 QUnit.module('setter methods'); 661 662 (function() { 663 QUnit.test('should only clone objects in `path`', function(assert) { 664 assert.expect(11); 665 666 var object = { 'a': { 'b': 2, 'c': 3 }, 'd': { 'e': 4 } }, 667 value = _.cloneDeep(object), 668 actual = fp.set('a.b.c.d', 5, value); 669 670 assert.ok(_.isObject(actual.a.b), 'fp.set'); 671 assert.ok(_.isNumber(actual.a.b), 'fp.set'); 672 673 assert.strictEqual(actual.a.b.c.d, 5, 'fp.set'); 674 assert.strictEqual(actual.d, value.d, 'fp.set'); 675 676 value = _.cloneDeep(object); 677 actual = fp.setWith(Object)('[0][1]')('a')(value); 678 679 assert.deepEqual(actual[0], { '1': 'a' }, 'fp.setWith'); 680 681 value = _.cloneDeep(object); 682 actual = fp.unset('a.b')(value); 683 684 assert.notOk('b' in actual.a, 'fp.unset'); 685 assert.strictEqual(actual.a.c, value.a.c, 'fp.unset'); 686 687 value = _.cloneDeep(object); 688 actual = fp.update('a.b')(square)(value); 689 690 assert.strictEqual(actual.a.b, 4, 'fp.update'); 691 assert.strictEqual(actual.d, value.d, 'fp.update'); 692 693 value = _.cloneDeep(object); 694 actual = fp.updateWith(Object)('[0][1]')(_.constant('a'))(value); 695 696 assert.deepEqual(actual[0], { '1': 'a' }, 'fp.updateWith'); 697 assert.strictEqual(actual.d, value.d, 'fp.updateWith'); 698 }); 699 }()); 700 701 /*--------------------------------------------------------------------------*/ 702 703 QUnit.module('fp.add and fp.subtract'); 704 705 _.each(['add', 'subtract'], function(methodName) { 706 var func = fp[methodName], 707 isAdd = methodName == 'add'; 708 709 QUnit.test('`fp.' + methodName + '` should not have `rearg` applied', function(assert) { 710 assert.expect(1); 711 712 assert.strictEqual(func('1')('2'), isAdd ? '12' : -1); 713 }); 714 }); 715 716 /*--------------------------------------------------------------------------*/ 717 718 QUnit.module('object assignments'); 719 720 _.each(['assign', 'assignIn', 'defaults', 'defaultsDeep', 'merge'], function(methodName) { 721 var func = fp[methodName]; 722 723 QUnit.test('`fp.' + methodName + '` should not mutate values', function(assert) { 724 assert.expect(2); 725 726 var object = { 'a': 1 }, 727 actual = func(object)({ 'b': 2 }); 728 729 assert.deepEqual(object, { 'a': 1 }); 730 assert.deepEqual(actual, { 'a': 1, 'b': 2 }); 731 }); 732 }); 733 734 _.each(['assignAll', 'assignInAll', 'defaultsAll', 'defaultsDeepAll', 'mergeAll'], function(methodName) { 735 var func = fp[methodName]; 736 737 QUnit.test('`fp.' + methodName + '` should not mutate values', function(assert) { 738 assert.expect(2); 739 740 var objects = [{ 'a': 1 }, { 'b': 2 }], 741 actual = func(objects); 742 743 assert.deepEqual(objects[0], { 'a': 1 }); 744 assert.deepEqual(actual, { 'a': 1, 'b': 2 }); 745 }); 746 }); 747 748 _.each(['assignWith', 'assignInWith', 'extendWith'], function(methodName) { 749 var func = fp[methodName]; 750 751 QUnit.test('`fp.' + methodName + '` should provide the correct `customizer` arguments', function(assert) { 752 assert.expect(1); 753 754 var args; 755 756 func(function() { 757 args || (args = _.map(arguments, _.cloneDeep)); 758 })({ 'a': 1 })({ 'b': 2 }); 759 760 assert.deepEqual(args, [undefined, 2, 'b', { 'a': 1 }, { 'b': 2 }]); 761 }); 762 }); 763 764 _.each(['assignAllWith', 'assignInAllWith', 'extendAllWith', 'mergeAllWith'], function(methodName) { 765 var func = fp[methodName]; 766 767 QUnit.test('`fp.' + methodName + '` should not mutate values', function(assert) { 768 assert.expect(2); 769 770 var objects = [{ 'a': 1 }, { 'b': 2 }], 771 actual = func(_.noop)(objects); 772 773 assert.deepEqual(objects[0], { 'a': 1 }); 774 assert.deepEqual(actual, { 'a': 1, 'b': 2 }); 775 }); 776 777 QUnit.test('`fp.' + methodName + '` should work with more than two sources', function(assert) { 778 assert.expect(2); 779 780 var pass = false, 781 objects = [{ 'a': 1 }, { 'b': 2 }, { 'c': 3 }], 782 actual = func(function() { pass = true; })(objects); 783 784 assert.ok(pass); 785 assert.deepEqual(actual, { 'a': 1, 'b': 2, 'c': 3 }); 786 }); 787 }); 788 789 /*--------------------------------------------------------------------------*/ 790 791 QUnit.module('fp.castArray'); 792 793 (function() { 794 QUnit.test('should shallow clone array values', function(assert) { 795 assert.expect(2); 796 797 var array = [1], 798 actual = fp.castArray(array); 799 800 assert.deepEqual(actual, array); 801 assert.notStrictEqual(actual, array); 802 }); 803 804 QUnit.test('should not shallow clone non-array values', function(assert) { 805 assert.expect(2); 806 807 var object = { 'a': 1 }, 808 actual = fp.castArray(object); 809 810 assert.deepEqual(actual, [object]); 811 assert.strictEqual(actual[0], object); 812 }); 813 814 QUnit.test('should convert by name', function(assert) { 815 assert.expect(4); 816 817 var array = [1], 818 object = { 'a': 1 }, 819 castArray = convert('castArray', _.castArray), 820 actual = castArray(array); 821 822 assert.deepEqual(actual, array); 823 assert.notStrictEqual(actual, array); 824 825 actual = castArray(object); 826 assert.deepEqual(actual, [object]); 827 assert.strictEqual(actual[0], object); 828 }); 829 }()); 830 831 /*--------------------------------------------------------------------------*/ 832 833 QUnit.module('curry methods'); 834 835 _.each(['curry', 'curryRight'], function(methodName) { 836 var func = fp[methodName]; 837 838 QUnit.test('fp.' + methodName + '` should only accept a `func` param', function(assert) { 839 assert.expect(1); 840 841 assert.raises(function() { func(1, _.noop); }, TypeError); 842 }); 843 }); 844 845 /*--------------------------------------------------------------------------*/ 846 847 QUnit.module('curryN methods'); 848 849 _.each(['curryN', 'curryRightN'], function(methodName) { 850 var func = fp[methodName]; 851 852 QUnit.test('fp.' + methodName + '` should accept an `arity` param', function(assert) { 853 assert.expect(1); 854 855 var actual = func(1)(function(a, b) { return [a, b]; })('a'); 856 assert.deepEqual(actual, ['a', undefined]); 857 }); 858 }); 859 860 /*--------------------------------------------------------------------------*/ 861 862 QUnit.module('fp.defaultTo'); 863 864 (function() { 865 QUnit.test('should have an argument order of `defaultValue` then `value`', function(assert) { 866 assert.expect(2); 867 868 assert.strictEqual(fp.defaultTo(1)(0), 0); 869 assert.strictEqual(fp.defaultTo(1)(undefined), 1); 870 }); 871 }()); 872 873 /*--------------------------------------------------------------------------*/ 874 875 QUnit.module('fp.difference'); 876 877 (function() { 878 QUnit.test('should return the elements of the first array not included in the second array', function(assert) { 879 assert.expect(1); 880 881 var actual = fp.difference([2, 1], [2, 3]); 882 assert.deepEqual(actual, [1]); 883 }); 884 }()); 885 886 /*--------------------------------------------------------------------------*/ 887 888 QUnit.module('fp.differenceBy'); 889 890 (function() { 891 QUnit.test('should have an argument order of `iteratee`, `array`, then `values`', function(assert) { 892 assert.expect(1); 893 894 var actual = fp.differenceBy(Math.floor, [2.1, 1.2], [2.3, 3.4]); 895 assert.deepEqual(actual, [1.2]); 896 }); 897 898 QUnit.test('should provide the correct `iteratee` arguments', function(assert) { 899 assert.expect(1); 900 901 var args; 902 903 fp.differenceBy(function() { 904 args || (args = slice.call(arguments)); 905 })([2.1, 1.2], [2.3, 3.4]); 906 907 assert.deepEqual(args, [2.3]); 908 }); 909 }()); 910 911 /*--------------------------------------------------------------------------*/ 912 913 QUnit.module('fp.differenceWith'); 914 915 (function() { 916 QUnit.test('should have an argument order of `comparator`, `array`, then `values`', function(assert) { 917 assert.expect(1); 918 919 var actual = fp.differenceWith(fp.eq)([2, 1])([2, 3]); 920 assert.deepEqual(actual, [1]); 921 }); 922 }()); 923 924 /*--------------------------------------------------------------------------*/ 925 926 QUnit.module('fp.divide and fp.multiply'); 927 928 _.each(['divide', 'multiply'], function(methodName) { 929 var func = fp[methodName], 930 isDivide = methodName == 'divide'; 931 932 QUnit.test('`fp.' + methodName + '` should not have `rearg` applied', function(assert) { 933 assert.expect(1); 934 935 assert.strictEqual(func('2')('4'), isDivide ? 0.5 : 8); 936 }); 937 }); 938 939 /*--------------------------------------------------------------------------*/ 940 941 QUnit.module('fp.extend'); 942 943 (function() { 944 QUnit.test('should convert by name', function(assert) { 945 assert.expect(2); 946 947 function Foo() {} 948 Foo.prototype = { 'b': 2 }; 949 950 var object = { 'a': 1 }, 951 extend = convert('extend', _.extend), 952 actual = extend(object)(new Foo); 953 954 assert.deepEqual(object, { 'a': 1 }); 955 assert.deepEqual(actual, { 'a': 1, 'b': 2 }); 956 }); 957 }()); 958 959 /*--------------------------------------------------------------------------*/ 960 961 QUnit.module('fp.fill'); 962 963 (function() { 964 QUnit.test('should have an argument order of `start`, `end`, then `value`', function(assert) { 965 assert.expect(1); 966 967 var array = [1, 2, 3]; 968 assert.deepEqual(fp.fill(1)(2)('*')(array), [1, '*', 3]); 969 }); 970 971 QUnit.test('should not mutate values', function(assert) { 972 assert.expect(2); 973 974 var array = [1, 2, 3], 975 actual = fp.fill(1)(2)('*')(array); 976 977 assert.deepEqual(array, [1, 2, 3]); 978 assert.deepEqual(actual, [1, '*', 3]); 979 }); 980 }()); 981 982 /*--------------------------------------------------------------------------*/ 983 984 QUnit.module('fp.findFrom methods'); 985 986 _.each(['findFrom', 'findIndexFrom', 'findLastFrom', 'findLastIndexFrom'], function(methodName) { 987 var func = fp[methodName]; 988 989 QUnit.test('fp.' + methodName + '` should provide the correct `predicate` arguments', function(assert) { 990 assert.expect(1); 991 992 var args; 993 994 func(function() { 995 args || (args = slice.call(arguments)); 996 })(1)([1, 2, 3]); 997 998 assert.deepEqual(args, [2]); 999 }); 1000 }); 1001 1002 /*--------------------------------------------------------------------------*/ 1003 1004 QUnit.module('fp.findFrom'); 1005 1006 (function() { 1007 function resolve(value) { 1008 return fp.flow(fp.property('a'), fp.eq(value)); 1009 } 1010 1011 QUnit.test('should have an argument order of `value`, `fromIndex`, then `array`', function(assert) { 1012 assert.expect(2); 1013 1014 var objects = [{ 'a': 1 }, { 'a': 2 }, { 'a': 1 }, { 'a': 2 }]; 1015 1016 assert.strictEqual(fp.findFrom(resolve(1))(1)(objects), objects[2]); 1017 assert.strictEqual(fp.findFrom(resolve(2))(-2)(objects), objects[3]); 1018 }); 1019 }()); 1020 1021 /*--------------------------------------------------------------------------*/ 1022 1023 QUnit.module('fp.findLastFrom'); 1024 1025 (function() { 1026 function resolve(value) { 1027 return fp.flow(fp.property('a'), fp.eq(value)); 1028 } 1029 1030 QUnit.test('should have an argument order of `value`, `fromIndex`, then `array`', function(assert) { 1031 assert.expect(2); 1032 1033 var objects = [{ 'a': 1 }, { 'a': 2 }, { 'a': 1 }, { 'a': 2 }]; 1034 1035 assert.strictEqual(fp.findLastFrom(resolve(1))(1)(objects), objects[0]); 1036 assert.strictEqual(fp.findLastFrom(resolve(2))(-2)(objects), objects[1]); 1037 }); 1038 }()); 1039 1040 /*--------------------------------------------------------------------------*/ 1041 1042 QUnit.module('fp.findIndexFrom and fp.indexOfFrom'); 1043 1044 _.each(['findIndexFrom', 'indexOfFrom'], function(methodName) { 1045 var func = fp[methodName], 1046 resolve = methodName == 'findIndexFrom' ? fp.eq : _.identity; 1047 1048 QUnit.test('fp.' + methodName + '` should have an argument order of `value`, `fromIndex`, then `array`', function(assert) { 1049 assert.expect(2); 1050 1051 var array = [1, 2, 3, 1, 2, 3]; 1052 1053 assert.strictEqual(func(resolve(1))(2)(array), 3); 1054 assert.strictEqual(func(resolve(2))(-3)(array), 4); 1055 }); 1056 }); 1057 1058 /*--------------------------------------------------------------------------*/ 1059 1060 QUnit.module('fp.findLastIndexFrom and fp.lastIndexOfFrom'); 1061 1062 _.each(['findLastIndexFrom', 'lastIndexOfFrom'], function(methodName) { 1063 var func = fp[methodName], 1064 resolve = methodName == 'findLastIndexFrom' ? fp.eq : _.identity; 1065 1066 QUnit.test('fp.' + methodName + '` should have an argument order of `value`, `fromIndex`, then `array`', function(assert) { 1067 assert.expect(2); 1068 1069 var array = [1, 2, 3, 1, 2, 3]; 1070 1071 assert.strictEqual(func(resolve(2))(3)(array), 1); 1072 assert.strictEqual(func(resolve(3))(-3)(array), 2); 1073 }); 1074 }); 1075 1076 /*--------------------------------------------------------------------------*/ 1077 1078 QUnit.module('fp.flatMapDepth'); 1079 1080 (function() { 1081 QUnit.test('should have an argument order of `iteratee`, `depth`, then `collection`', function(assert) { 1082 assert.expect(2); 1083 1084 function duplicate(n) { 1085 return [[[n, n]]]; 1086 } 1087 1088 var array = [1, 2], 1089 object = { 'a': 1, 'b': 2 }, 1090 expected = [[1, 1], [2, 2]]; 1091 1092 assert.deepEqual(fp.flatMapDepth(duplicate)(2)(array), expected); 1093 assert.deepEqual(fp.flatMapDepth(duplicate)(2)(object), expected); 1094 }); 1095 }()); 1096 1097 /*--------------------------------------------------------------------------*/ 1098 1099 QUnit.module('flow methods'); 1100 1101 _.each(['flow', 'flowRight'], function(methodName) { 1102 var func = fp[methodName], 1103 isFlow = methodName == 'flow'; 1104 1105 QUnit.test('`fp.' + methodName + '` should support shortcut fusion', function(assert) { 1106 assert.expect(6); 1107 1108 var filterCount, 1109 mapCount, 1110 array = fp.range(0, LARGE_ARRAY_SIZE); 1111 1112 var iteratee = function(value) { 1113 mapCount++; 1114 return square(value); 1115 }; 1116 1117 var predicate = function(value) { 1118 filterCount++; 1119 return isEven(value); 1120 }; 1121 1122 var filter = fp.filter(predicate), 1123 map = fp.map(iteratee), 1124 take = fp.take(2); 1125 1126 _.times(2, function(index) { 1127 var combined = isFlow 1128 ? func(map, filter, fp.compact, take) 1129 : func(take, fp.compact, filter, map); 1130 1131 filterCount = mapCount = 0; 1132 1133 if (WeakMap && WeakMap.name) { 1134 assert.deepEqual(combined(array), [4, 16]); 1135 assert.strictEqual(filterCount, 5, 'filterCount'); 1136 assert.strictEqual(mapCount, 5, 'mapCount'); 1137 } 1138 else { 1139 skipAssert(assert, 3); 1140 } 1141 }); 1142 }); 1143 }); 1144 1145 /*--------------------------------------------------------------------------*/ 1146 1147 QUnit.module('forEach methods'); 1148 1149 _.each(['forEach', 'forEachRight', 'forIn', 'forInRight', 'forOwn', 'forOwnRight'], function(methodName) { 1150 var func = fp[methodName]; 1151 1152 QUnit.test('`fp.' + methodName + '` should provide `value` to `iteratee`', function(assert) { 1153 assert.expect(2); 1154 1155 var args; 1156 1157 func(function() { 1158 args || (args = slice.call(arguments)); 1159 })(['a']); 1160 1161 assert.deepEqual(args, ['a']); 1162 1163 args = undefined; 1164 1165 func(function() { 1166 args || (args = slice.call(arguments)); 1167 })({ 'a': 1 }); 1168 1169 assert.deepEqual(args, [1]); 1170 }); 1171 }); 1172 1173 /*--------------------------------------------------------------------------*/ 1174 1175 QUnit.module('fp.getOr'); 1176 1177 (function() { 1178 QUnit.test('should accept a `defaultValue` param', function(assert) { 1179 assert.expect(1); 1180 1181 var actual = fp.getOr('default')('path')({}); 1182 assert.strictEqual(actual, 'default'); 1183 }); 1184 }()); 1185 1186 /*--------------------------------------------------------------------------*/ 1187 1188 QUnit.module('fp.gt and fp.gte'); 1189 1190 _.each(['gt', 'gte'], function(methodName) { 1191 var func = fp[methodName]; 1192 1193 QUnit.test('`fp.' + methodName + '` should have `rearg` applied', function(assert) { 1194 assert.expect(1); 1195 1196 assert.strictEqual(func(2)(1), true); 1197 }); 1198 }); 1199 1200 /*--------------------------------------------------------------------------*/ 1201 1202 QUnit.module('fp.inRange'); 1203 1204 (function() { 1205 QUnit.test('should have an argument order of `start`, `end`, then `value`', function(assert) { 1206 assert.expect(2); 1207 1208 assert.strictEqual(fp.inRange(2)(4)(3), true); 1209 assert.strictEqual(fp.inRange(-2)(-6)(-3), true); 1210 }); 1211 }()); 1212 1213 /*--------------------------------------------------------------------------*/ 1214 1215 QUnit.module('fp.intersectionBy'); 1216 1217 (function() { 1218 QUnit.test('should have an argument order of `iteratee`, `array`, then `values`', function(assert) { 1219 assert.expect(1); 1220 1221 var actual = fp.intersectionBy(Math.floor, [2.1, 1.2], [2.3, 3.4]); 1222 assert.deepEqual(actual, [2.1]); 1223 }); 1224 1225 QUnit.test('should provide the correct `iteratee` arguments', function(assert) { 1226 assert.expect(1); 1227 1228 var args; 1229 1230 fp.intersectionBy(function() { 1231 args || (args = slice.call(arguments)); 1232 })([2.1, 1.2], [2.3, 3.4]); 1233 1234 assert.deepEqual(args, [2.3]); 1235 }); 1236 }()); 1237 1238 /*--------------------------------------------------------------------------*/ 1239 1240 QUnit.module('fp.intersectionWith'); 1241 1242 (function() { 1243 QUnit.test('should have an argument order of `comparator`, `array`, then `values`', function(assert) { 1244 assert.expect(1); 1245 1246 var actual = fp.intersectionWith(fp.eq)([2, 1])([2, 3]); 1247 assert.deepEqual(actual, [2]); 1248 }); 1249 }()); 1250 1251 /*--------------------------------------------------------------------------*/ 1252 1253 QUnit.module('fp.invoke'); 1254 1255 (function() { 1256 QUnit.test('should not accept an `args` param', function(assert) { 1257 assert.expect(1); 1258 1259 var actual = fp.invoke('toUpperCase')('a'); 1260 assert.strictEqual(actual, 'A'); 1261 }); 1262 }()); 1263 1264 /*--------------------------------------------------------------------------*/ 1265 1266 QUnit.module('fp.invokeMap'); 1267 1268 (function() { 1269 QUnit.test('should not accept an `args` param', function(assert) { 1270 assert.expect(1); 1271 1272 var actual = fp.invokeMap('toUpperCase')(['a', 'b']); 1273 assert.deepEqual(actual, ['A', 'B']); 1274 }); 1275 }()); 1276 1277 /*--------------------------------------------------------------------------*/ 1278 1279 QUnit.module('fp.invokeArgs'); 1280 1281 (function() { 1282 QUnit.test('should accept an `args` param', function(assert) { 1283 assert.expect(1); 1284 1285 var actual = fp.invokeArgs('concat')(['b', 'c'])('a'); 1286 assert.strictEqual(actual, 'abc'); 1287 }); 1288 }()); 1289 1290 /*--------------------------------------------------------------------------*/ 1291 1292 QUnit.module('fp.invokeArgsMap'); 1293 1294 (function() { 1295 QUnit.test('should accept an `args` param', function(assert) { 1296 assert.expect(1); 1297 1298 var actual = fp.invokeArgsMap('concat')(['b', 'c'])(['a', 'A']); 1299 assert.deepEqual(actual, ['abc', 'Abc']); 1300 }); 1301 }()); 1302 1303 /*--------------------------------------------------------------------------*/ 1304 1305 QUnit.module('fp.isEqualWith'); 1306 1307 (function() { 1308 QUnit.test('should provide the correct `customizer` arguments', function(assert) { 1309 assert.expect(1); 1310 1311 var args, 1312 iteration = 0, 1313 objects = [{ 'a': 1 }, { 'a': 2 }], 1314 stack = { '__data__': { '__data__': [objects, objects.slice().reverse()], 'size': 2 }, 'size': 2 }, 1315 expected = [1, 2, 'a', objects[0], objects[1], stack]; 1316 1317 fp.isEqualWith(function() { 1318 if (++iteration == 2) { 1319 args = _.map(arguments, _.cloneDeep); 1320 } 1321 })(objects[0])(objects[1]); 1322 1323 args[5] = _.omitBy(args[5], _.isFunction); 1324 args[5].__data__ = _.omitBy(args[5].__data__, _.isFunction); 1325 1326 assert.deepEqual(args, expected); 1327 }); 1328 }()); 1329 1330 /*--------------------------------------------------------------------------*/ 1331 1332 QUnit.module('fp.isMatchWith'); 1333 1334 (function() { 1335 QUnit.test('should provide the correct `customizer` arguments', function(assert) { 1336 assert.expect(1); 1337 1338 var args, 1339 objects = [{ 'a': 1 }, { 'a': 2 }], 1340 stack = { '__data__': { '__data__': [], 'size': 0 }, 'size': 0 }, 1341 expected = [2, 1, 'a', objects[1], objects[0], stack]; 1342 1343 fp.isMatchWith(function() { 1344 args || (args = _.map(arguments, _.cloneDeep)); 1345 })(objects[0])(objects[1]); 1346 1347 args[5] = _.omitBy(args[5], _.isFunction); 1348 args[5].__data__ = _.omitBy(args[5].__data__, _.isFunction); 1349 1350 assert.deepEqual(args, expected); 1351 }); 1352 }()); 1353 1354 /*--------------------------------------------------------------------------*/ 1355 1356 QUnit.module('fp.iteratee'); 1357 1358 (function() { 1359 QUnit.test('should return a iteratee with capped params', function(assert) { 1360 assert.expect(1); 1361 1362 var func = fp.iteratee(function(a, b, c) { return [a, b, c]; }, 3); 1363 assert.deepEqual(func(1, 2, 3), [1, undefined, undefined]); 1364 }); 1365 1366 QUnit.test('should convert by name', function(assert) { 1367 assert.expect(1); 1368 1369 var iteratee = convert('iteratee', _.iteratee), 1370 func = iteratee(function(a, b, c) { return [a, b, c]; }, 3); 1371 1372 assert.deepEqual(func(1, 2, 3), [1, undefined, undefined]); 1373 }); 1374 }()); 1375 1376 /*--------------------------------------------------------------------------*/ 1377 1378 QUnit.module('fp.lt and fp.lte'); 1379 1380 _.each(['lt', 'lte'], function(methodName) { 1381 var func = fp[methodName]; 1382 1383 QUnit.test('`fp.' + methodName + '` should have `rearg` applied', function(assert) { 1384 assert.expect(1); 1385 1386 assert.strictEqual(func(1)(2), true); 1387 }); 1388 }); 1389 1390 /*--------------------------------------------------------------------------*/ 1391 1392 QUnit.module('fp.mapKeys'); 1393 1394 (function() { 1395 QUnit.test('should only provide `key` to `iteratee`', function(assert) { 1396 assert.expect(1); 1397 1398 var args; 1399 1400 fp.mapKeys(function() { 1401 args || (args = slice.call(arguments)); 1402 }, { 'a': 1 }); 1403 1404 assert.deepEqual(args, ['a']); 1405 }); 1406 }()); 1407 1408 /*--------------------------------------------------------------------------*/ 1409 1410 QUnit.module('fp.maxBy and fp.minBy'); 1411 1412 _.each(['maxBy', 'minBy'], function(methodName) { 1413 var array = [1, 2, 3], 1414 func = fp[methodName], 1415 isMax = methodName == 'maxBy'; 1416 1417 QUnit.test('`fp.' + methodName + '` should work with an `iteratee` argument', function(assert) { 1418 assert.expect(1); 1419 1420 var actual = func(function(num) { 1421 return -num; 1422 })(array); 1423 1424 assert.strictEqual(actual, isMax ? 1 : 3); 1425 }); 1426 1427 QUnit.test('`fp.' + methodName + '` should provide the correct `iteratee` arguments', function(assert) { 1428 assert.expect(1); 1429 1430 var args; 1431 1432 func(function() { 1433 args || (args = slice.call(arguments)); 1434 })(array); 1435 1436 assert.deepEqual(args, [1]); 1437 }); 1438 }); 1439 1440 /*--------------------------------------------------------------------------*/ 1441 1442 QUnit.module('fp.mergeWith'); 1443 1444 (function() { 1445 QUnit.test('should provide the correct `customizer` arguments', function(assert) { 1446 assert.expect(1); 1447 1448 var args, 1449 stack = { '__data__': { '__data__': [], 'size': 0 }, 'size': 0 }, 1450 expected = [[1, 2], [3], 'a', { 'a': [1, 2] }, { 'a': [3] }, stack]; 1451 1452 fp.mergeWith(function() { 1453 args || (args = _.map(arguments, _.cloneDeep)); 1454 })({ 'a': [1, 2] })({ 'a': [3] }); 1455 1456 args[5] = _.omitBy(args[5], _.isFunction); 1457 args[5].__data__ = _.omitBy(args[5].__data__, _.isFunction); 1458 1459 assert.deepEqual(args, expected); 1460 }); 1461 1462 QUnit.test('should not mutate values', function(assert) { 1463 assert.expect(2); 1464 1465 var objects = [{ 'a': [1, 2] }, { 'a': [3] }], 1466 actual = fp.mergeWith(_.noop, objects[0], objects[1]); 1467 1468 assert.deepEqual(objects[0], { 'a': [1, 2] }); 1469 assert.deepEqual(actual, { 'a': [3, 2] }); 1470 }); 1471 }()); 1472 1473 /*--------------------------------------------------------------------------*/ 1474 1475 QUnit.module('fp.mergeAllWith'); 1476 1477 (function() { 1478 QUnit.test('should provide the correct `customizer` arguments', function(assert) { 1479 assert.expect(1); 1480 1481 var args, 1482 objects = [{ 'a': [1, 2] }, { 'a': [3] }], 1483 stack = { '__data__': { '__data__': [], 'size': 0 }, 'size': 0 }, 1484 expected = [[1, 2], [3], 'a', { 'a': [1, 2] }, { 'a': [3] }, stack]; 1485 1486 fp.mergeAllWith(function() { 1487 args || (args = _.map(arguments, _.cloneDeep)); 1488 })(objects); 1489 1490 args[5] = _.omitBy(args[5], _.isFunction); 1491 args[5].__data__ = _.omitBy(args[5].__data__, _.isFunction); 1492 1493 assert.deepEqual(args, expected); 1494 }); 1495 }()); 1496 1497 /*--------------------------------------------------------------------------*/ 1498 1499 QUnit.module('fp.mixin'); 1500 1501 (function() { 1502 var source = { 'a': _.noop }; 1503 1504 QUnit.test('should mixin static methods but not prototype methods', function(assert) { 1505 assert.expect(2); 1506 1507 fp.mixin(source); 1508 1509 assert.strictEqual(typeof fp.a, 'function'); 1510 assert.notOk('a' in fp.prototype); 1511 1512 delete fp.a; 1513 delete fp.prototype.a; 1514 }); 1515 1516 QUnit.test('should not assign inherited `source` methods', function(assert) { 1517 assert.expect(2); 1518 1519 function Foo() {} 1520 Foo.prototype.a = _.noop; 1521 fp.mixin(new Foo); 1522 1523 assert.notOk('a' in fp); 1524 assert.notOk('a' in fp.prototype); 1525 1526 delete fp.a; 1527 delete fp.prototype.a; 1528 }); 1529 1530 QUnit.test('should not remove existing prototype methods', function(assert) { 1531 assert.expect(2); 1532 1533 var each1 = fp.each, 1534 each2 = fp.prototype.each; 1535 1536 fp.mixin({ 'each': source.a }); 1537 1538 assert.strictEqual(fp.each, source.a); 1539 assert.strictEqual(fp.prototype.each, each2); 1540 1541 fp.each = each1; 1542 fp.prototype.each = each2; 1543 }); 1544 1545 QUnit.test('should not export to the global when `source` is not an object', function(assert) { 1546 assert.expect(2); 1547 1548 var props = _.without(_.keys(_), '_'); 1549 1550 _.times(2, function(index) { 1551 fp.mixin.apply(fp, index ? [1] : []); 1552 1553 assert.ok(_.every(props, function(key) { 1554 return root[key] !== fp[key]; 1555 })); 1556 1557 _.each(props, function(key) { 1558 if (root[key] === fp[key]) { 1559 delete root[key]; 1560 } 1561 }); 1562 }); 1563 }); 1564 1565 QUnit.test('should convert by name', function(assert) { 1566 assert.expect(3); 1567 1568 var object = { 'mixin': convert('mixin', _.mixin) }; 1569 1570 function Foo() {} 1571 Foo.mixin = object.mixin; 1572 Foo.mixin(source); 1573 1574 assert.ok('a' in Foo); 1575 assert.notOk('a' in Foo.prototype); 1576 1577 object.mixin(source); 1578 assert.ok('a' in object); 1579 }); 1580 }()); 1581 1582 /*--------------------------------------------------------------------------*/ 1583 1584 QUnit.module('fp.nthArg'); 1585 1586 (function() { 1587 QUnit.test('should return a curried function', function(assert) { 1588 assert.expect(2); 1589 1590 var func = fp.nthArg(1); 1591 assert.strictEqual(func(1)(2), 2); 1592 1593 func = fp.nthArg(-1); 1594 assert.strictEqual(func(1), 1); 1595 }); 1596 }()); 1597 1598 /*--------------------------------------------------------------------------*/ 1599 1600 QUnit.module('fp.over'); 1601 1602 (function() { 1603 QUnit.test('should not cap iteratee args', function(assert) { 1604 assert.expect(2); 1605 1606 _.each([fp.over, convert('over', _.over)], function(func) { 1607 var over = func([Math.max, Math.min]); 1608 assert.deepEqual(over(1, 2, 3, 4), [4, 1]); 1609 }); 1610 }); 1611 }()); 1612 1613 /*--------------------------------------------------------------------------*/ 1614 1615 QUnit.module('fp.omitBy and fp.pickBy'); 1616 1617 _.each(['omitBy', 'pickBy'], function(methodName) { 1618 var func = fp[methodName]; 1619 1620 QUnit.test('`fp.' + methodName + '` should provide `value` and `key` to `iteratee`', function(assert) { 1621 assert.expect(1); 1622 1623 var args; 1624 1625 func(function() { 1626 args || (args = slice.call(arguments)); 1627 })({ 'a': 1 }); 1628 1629 assert.deepEqual(args, [1, 'a']); 1630 }); 1631 }); 1632 1633 /*--------------------------------------------------------------------------*/ 1634 1635 QUnit.module('padChars methods'); 1636 1637 _.each(['padChars', 'padCharsStart', 'padCharsEnd'], function(methodName) { 1638 var func = fp[methodName], 1639 isPad = methodName == 'padChars', 1640 isStart = methodName == 'padCharsStart'; 1641 1642 QUnit.test('fp.' + methodName + '` should truncate pad characters to fit the pad length', function(assert) { 1643 assert.expect(1); 1644 1645 if (isPad) { 1646 assert.strictEqual(func('_-')(8)('abc'), '_-abc_-_'); 1647 } else { 1648 assert.strictEqual(func('_-')(6)('abc'), isStart ? '_-_abc' : 'abc_-_'); 1649 } 1650 }); 1651 }); 1652 1653 /*--------------------------------------------------------------------------*/ 1654 1655 QUnit.module('partial methods'); 1656 1657 _.each(['partial', 'partialRight'], function(methodName) { 1658 var func = fp[methodName], 1659 isPartial = methodName == 'partial'; 1660 1661 QUnit.test('fp.' + methodName + '` should accept an `args` param', function(assert) { 1662 assert.expect(1); 1663 1664 var expected = isPartial ? [1, 2, 3] : [0, 1, 2]; 1665 1666 var actual = func(function(a, b, c) { 1667 return [a, b, c]; 1668 })([1, 2])(isPartial ? 3 : 0); 1669 1670 assert.deepEqual(actual, expected); 1671 }); 1672 1673 QUnit.test('fp.' + methodName + '` should convert by name', function(assert) { 1674 assert.expect(2); 1675 1676 var expected = isPartial ? [1, 2, 3] : [0, 1, 2], 1677 par = convert(methodName, _[methodName]), 1678 ph = par.placeholder; 1679 1680 var actual = par(function(a, b, c) { 1681 return [a, b, c]; 1682 })([1, 2])(isPartial ? 3 : 0); 1683 1684 assert.deepEqual(actual, expected); 1685 1686 actual = par(function(a, b, c) { 1687 return [a, b, c]; 1688 })([ph, 2])(isPartial ? 1 : 0, isPartial ? 3 : 1); 1689 1690 assert.deepEqual(actual, expected); 1691 }); 1692 }); 1693 1694 /*--------------------------------------------------------------------------*/ 1695 1696 QUnit.module('fp.propertyOf'); 1697 1698 (function() { 1699 QUnit.test('should be curried', function(assert) { 1700 assert.expect(2); 1701 1702 var object = { 'a': 1 }; 1703 1704 assert.strictEqual(fp.propertyOf(object, 'a'), 1); 1705 assert.strictEqual(fp.propertyOf(object)('a'), 1); 1706 }); 1707 }()); 1708 1709 /*--------------------------------------------------------------------------*/ 1710 1711 QUnit.module('fp.pull'); 1712 1713 (function() { 1714 QUnit.test('should not mutate values', function(assert) { 1715 assert.expect(2); 1716 1717 var array = [1, 2, 3], 1718 actual = fp.pull(2)(array); 1719 1720 assert.deepEqual(array, [1, 2, 3]); 1721 assert.deepEqual(actual, [1, 3]); 1722 }); 1723 }()); 1724 1725 /*--------------------------------------------------------------------------*/ 1726 1727 QUnit.module('fp.pullAll'); 1728 1729 (function() { 1730 QUnit.test('should not mutate values', function(assert) { 1731 assert.expect(2); 1732 1733 var array = [1, 2, 3], 1734 actual = fp.pullAll([1, 3])(array); 1735 1736 assert.deepEqual(array, [1, 2, 3]); 1737 assert.deepEqual(actual, [2]); 1738 }); 1739 }()); 1740 1741 /*--------------------------------------------------------------------------*/ 1742 1743 QUnit.module('fp.pullAt'); 1744 1745 (function() { 1746 QUnit.test('should not mutate values', function(assert) { 1747 assert.expect(2); 1748 1749 var array = [1, 2, 3], 1750 actual = fp.pullAt([0, 2])(array); 1751 1752 assert.deepEqual(array, [1, 2, 3]); 1753 assert.deepEqual(actual, [2]); 1754 }); 1755 }()); 1756 1757 /*--------------------------------------------------------------------------*/ 1758 1759 QUnit.module('fp.random'); 1760 1761 (function() { 1762 var array = Array(1000); 1763 1764 QUnit.test('should support a `min` and `max` argument', function(assert) { 1765 assert.expect(1); 1766 1767 var min = 5, 1768 max = 10; 1769 1770 assert.ok(_.some(array, function() { 1771 var result = fp.random(min)(max); 1772 return result >= min && result <= max; 1773 })); 1774 }); 1775 }()); 1776 1777 /*--------------------------------------------------------------------------*/ 1778 1779 QUnit.module('range methods'); 1780 1781 _.each(['range', 'rangeRight'], function(methodName) { 1782 var func = fp[methodName], 1783 isRange = methodName == 'range'; 1784 1785 QUnit.test('fp.' + methodName + '` should have an argument order of `start` then `end`', function(assert) { 1786 assert.expect(1); 1787 1788 assert.deepEqual(func(1)(4), isRange ? [1, 2, 3] : [3, 2, 1]); 1789 }); 1790 }); 1791 1792 /*--------------------------------------------------------------------------*/ 1793 1794 QUnit.module('rangeStep methods'); 1795 1796 _.each(['rangeStep', 'rangeStepRight'], function(methodName) { 1797 var func = fp[methodName], 1798 isRange = methodName == 'rangeStep'; 1799 1800 QUnit.test('fp.' + methodName + '` should have an argument order of `step`, `start`, then `end`', function(assert) { 1801 assert.expect(1); 1802 1803 assert.deepEqual(func(2)(1)(4), isRange ? [1, 3] : [3, 1]); 1804 }); 1805 }); 1806 1807 /*--------------------------------------------------------------------------*/ 1808 1809 QUnit.module('fp.rearg'); 1810 1811 (function() { 1812 function fn(a, b, c) { 1813 return [a, b, c]; 1814 } 1815 1816 QUnit.test('should be curried', function(assert) { 1817 assert.expect(1); 1818 1819 var rearged = fp.rearg([1, 2, 0])(fn); 1820 assert.deepEqual(rearged('c', 'a', 'b'), ['a', 'b', 'c']); 1821 }); 1822 1823 QUnit.test('should return a curried function', function(assert) { 1824 assert.expect(1); 1825 1826 var rearged = fp.rearg([1, 2, 0], fn); 1827 assert.deepEqual(rearged('c')('a')('b'), ['a', 'b', 'c']); 1828 }); 1829 }()); 1830 1831 /*--------------------------------------------------------------------------*/ 1832 1833 QUnit.module('reduce methods'); 1834 1835 _.each(['reduce', 'reduceRight'], function(methodName) { 1836 var func = fp[methodName], 1837 isReduce = methodName == 'reduce'; 1838 1839 QUnit.test('`fp.' + methodName + '` should provide the correct `iteratee` arguments when iterating an array', function(assert) { 1840 assert.expect(1); 1841 1842 var args; 1843 1844 func(function() { 1845 args || (args = slice.call(arguments)); 1846 })(0)([1, 2, 3]); 1847 1848 assert.deepEqual(args, isReduce ? [0, 1] : [3, 0]); 1849 }); 1850 1851 QUnit.test('`fp.' + methodName + '` should provide the correct `iteratee` arguments when iterating an object', function(assert) { 1852 assert.expect(1); 1853 1854 var args, 1855 object = { 'a': 1, 'b': 2 }, 1856 isFIFO = _.keys(object)[0] == 'a'; 1857 1858 var expected = isFIFO 1859 ? (isReduce ? [0, 1] : [2, 0]) 1860 : (isReduce ? [0, 2] : [1, 0]); 1861 1862 func(function() { 1863 args || (args = slice.call(arguments)); 1864 })(0)(object); 1865 1866 assert.deepEqual(args, expected); 1867 }); 1868 }); 1869 1870 /*--------------------------------------------------------------------------*/ 1871 1872 QUnit.module('fp.remove'); 1873 1874 (function() { 1875 QUnit.test('should not mutate values', function(assert) { 1876 assert.expect(2); 1877 1878 var array = [1, 2, 3], 1879 actual = fp.remove(fp.eq(2))(array); 1880 1881 assert.deepEqual(array, [1, 2, 3]); 1882 assert.deepEqual(actual, [1, 3]); 1883 }); 1884 }()); 1885 1886 /*--------------------------------------------------------------------------*/ 1887 1888 QUnit.module('fp.restFrom'); 1889 1890 (function() { 1891 QUnit.test('should accept a `start` param', function(assert) { 1892 assert.expect(1); 1893 1894 var actual = fp.restFrom(2)(function() { 1895 return slice.call(arguments); 1896 })('a', 'b', 'c', 'd'); 1897 1898 assert.deepEqual(actual, ['a', 'b', ['c', 'd']]); 1899 }); 1900 }()); 1901 1902 /*--------------------------------------------------------------------------*/ 1903 1904 QUnit.module('fp.reverse'); 1905 1906 (function() { 1907 QUnit.test('should not mutate values', function(assert) { 1908 assert.expect(2); 1909 1910 var array = [1, 2, 3], 1911 actual = fp.reverse(array); 1912 1913 assert.deepEqual(array, [1, 2, 3]); 1914 assert.deepEqual(actual, [3, 2, 1]); 1915 }); 1916 }()); 1917 1918 /*--------------------------------------------------------------------------*/ 1919 1920 QUnit.module('fp.runInContext'); 1921 1922 (function() { 1923 QUnit.test('should return a converted lodash instance', function(assert) { 1924 assert.expect(1); 1925 1926 assert.strictEqual(typeof fp.runInContext({}).curryN, 'function'); 1927 }); 1928 1929 QUnit.test('should convert by name', function(assert) { 1930 assert.expect(1); 1931 1932 var runInContext = convert('runInContext', _.runInContext); 1933 assert.strictEqual(typeof runInContext({}).curryN, 'function'); 1934 }); 1935 }()); 1936 1937 /*--------------------------------------------------------------------------*/ 1938 1939 QUnit.module('fp.set'); 1940 1941 (function() { 1942 QUnit.test('should not mutate values', function(assert) { 1943 assert.expect(2); 1944 1945 var object = { 'a': { 'b': 2, 'c': 3 } }, 1946 actual = fp.set('a.b')(3)(object); 1947 1948 assert.deepEqual(object, { 'a': { 'b': 2, 'c': 3 } }); 1949 assert.deepEqual(actual, { 'a': { 'b': 3, 'c': 3 } }); 1950 }); 1951 }()); 1952 1953 /*--------------------------------------------------------------------------*/ 1954 1955 QUnit.module('fp.setWith'); 1956 1957 (function() { 1958 QUnit.test('should provide the correct `customizer` arguments', function(assert) { 1959 assert.expect(1); 1960 1961 var args; 1962 1963 fp.setWith(function() { 1964 args || (args = _.map(arguments, _.cloneDeep)); 1965 })('b.c')(2)({ 'a': 1 }); 1966 1967 assert.deepEqual(args, [undefined, 'b', { 'a': 1 }]); 1968 }); 1969 1970 QUnit.test('should not mutate values', function(assert) { 1971 assert.expect(2); 1972 1973 var object = { 'a': { 'b': 2, 'c': 3 } }, 1974 actual = fp.setWith(Object)('d.e')(4)(object); 1975 1976 assert.deepEqual(object, { 'a': { 'b': 2, 'c': 3 } }); 1977 assert.deepEqual(actual, { 'a': { 'b': 2, 'c': 3 }, 'd': { 'e': 4 } }); 1978 }); 1979 }()); 1980 1981 /*--------------------------------------------------------------------------*/ 1982 1983 QUnit.module('fp.spreadFrom'); 1984 1985 (function() { 1986 QUnit.test('should accept a `start` param', function(assert) { 1987 assert.expect(1); 1988 1989 var actual = fp.spreadFrom(2)(function() { 1990 return slice.call(arguments); 1991 })('a', 'b', ['c', 'd']); 1992 1993 assert.deepEqual(actual, ['a', 'b', 'c', 'd']); 1994 }); 1995 }()); 1996 1997 /*--------------------------------------------------------------------------*/ 1998 1999 QUnit.module('trimChars methods'); 2000 2001 _.each(['trimChars', 'trimCharsStart', 'trimCharsEnd'], function(methodName, index) { 2002 var func = fp[methodName], 2003 parts = []; 2004 2005 if (index != 2) { 2006 parts.push('leading'); 2007 } 2008 if (index != 1) { 2009 parts.push('trailing'); 2010 } 2011 parts = parts.join(' and '); 2012 2013 QUnit.test('`fp.' + methodName + '` should remove ' + parts + ' `chars`', function(assert) { 2014 assert.expect(1); 2015 2016 var string = '-_-a-b-c-_-', 2017 expected = (index == 2 ? '-_-' : '') + 'a-b-c' + (index == 1 ? '-_-' : ''); 2018 2019 assert.strictEqual(func('_-')(string), expected); 2020 }); 2021 }); 2022 2023 /*--------------------------------------------------------------------------*/ 2024 2025 QUnit.module('fp.unionBy'); 2026 2027 (function() { 2028 QUnit.test('should have an argument order of `iteratee`, `array`, then `other`', function(assert) { 2029 assert.expect(1); 2030 2031 var actual = fp.unionBy(Math.floor, [2.1], [1.2, 2.3]); 2032 assert.deepEqual(actual, [2.1, 1.2]); 2033 }); 2034 2035 QUnit.test('should provide the correct `iteratee` arguments', function(assert) { 2036 assert.expect(1); 2037 2038 var args; 2039 2040 fp.unionBy(function() { 2041 args || (args = slice.call(arguments)); 2042 })([2.1], [1.2, 2.3]); 2043 2044 assert.deepEqual(args, [2.1]); 2045 }); 2046 }()); 2047 2048 /*--------------------------------------------------------------------------*/ 2049 2050 QUnit.module('fp.unionWith'); 2051 2052 (function() { 2053 QUnit.test('should have an argument order of `comparator`, `array`, then `values`', function(assert) { 2054 assert.expect(1); 2055 2056 var actual = fp.unionWith(fp.eq)([2, 1])([2, 3]); 2057 assert.deepEqual(actual, [2, 1, 3]); 2058 }); 2059 2060 QUnit.test('should provide the correct `comparator` arguments', function(assert) { 2061 assert.expect(1); 2062 2063 var args; 2064 2065 fp.unionWith(function() { 2066 args || (args = slice.call(arguments)); 2067 })([2, 1])([2, 3]); 2068 2069 assert.deepEqual(args, [1, 2]); 2070 }); 2071 }()); 2072 2073 /*--------------------------------------------------------------------------*/ 2074 2075 QUnit.module('fp.uniqBy'); 2076 2077 (function() { 2078 var objects = [{ 'a': 2 }, { 'a': 3 }, { 'a': 1 }, { 'a': 2 }, { 'a': 3 }, { 'a': 1 }]; 2079 2080 QUnit.test('should work with an `iteratee` argument', function(assert) { 2081 assert.expect(1); 2082 2083 var expected = objects.slice(0, 3), 2084 actual = fp.uniqBy(_.property('a'))(objects); 2085 2086 assert.deepEqual(actual, expected); 2087 }); 2088 2089 QUnit.test('should provide the correct `iteratee` arguments', function(assert) { 2090 assert.expect(1); 2091 2092 var args; 2093 2094 fp.uniqBy(function() { 2095 args || (args = slice.call(arguments)); 2096 })(objects); 2097 2098 assert.deepEqual(args, [objects[0]]); 2099 }); 2100 }()); 2101 2102 /*--------------------------------------------------------------------------*/ 2103 2104 QUnit.module('fp.uniqWith'); 2105 2106 (function() { 2107 QUnit.test('should have an argument order of `comparator`, `array`, then `values`', function(assert) { 2108 assert.expect(1); 2109 2110 var actual = fp.uniqWith(fp.eq)([2, 1, 2]); 2111 assert.deepEqual(actual, [2, 1]); 2112 }); 2113 2114 QUnit.test('should provide the correct `comparator` arguments', function(assert) { 2115 assert.expect(1); 2116 2117 var args; 2118 2119 fp.uniqWith(function() { 2120 args || (args = slice.call(arguments)); 2121 })([2, 1, 2]); 2122 2123 assert.deepEqual(args, [1, 2]); 2124 }); 2125 }()); 2126 2127 /*--------------------------------------------------------------------------*/ 2128 2129 QUnit.module('fp.update'); 2130 2131 (function() { 2132 QUnit.test('should not convert end of `path` to an object', function(assert) { 2133 assert.expect(1); 2134 2135 var actual = fp.update('a.b')(_.identity)({ 'a': { 'b': 1 } }); 2136 assert.strictEqual(typeof actual.a.b, 'number'); 2137 }); 2138 2139 QUnit.test('should not convert uncloneables to objects', function(assert) { 2140 assert.expect(2); 2141 2142 var object = { 'a': { 'b': _.constant(true) } }, 2143 actual = fp.update('a.b')(_.identity)(object); 2144 2145 assert.strictEqual(typeof object.a.b, 'function'); 2146 assert.strictEqual(object.a.b, actual.a.b); 2147 }); 2148 2149 QUnit.test('should not mutate values', function(assert) { 2150 assert.expect(2); 2151 2152 var object = { 'a': { 'b': 2, 'c': 3 } }, 2153 actual = fp.update('a.b')(square)(object); 2154 2155 assert.deepEqual(object, { 'a': { 'b': 2, 'c': 3 } }); 2156 assert.deepEqual(actual, { 'a': { 'b': 4, 'c': 3 } }); 2157 }); 2158 }()); 2159 2160 /*--------------------------------------------------------------------------*/ 2161 2162 QUnit.module('fp.updateWith'); 2163 2164 (function() { 2165 QUnit.test('should provide the correct `customizer` arguments', function(assert) { 2166 var args; 2167 2168 fp.updateWith(function() { 2169 args || (args = _.map(arguments, _.cloneDeep)); 2170 })('b.c')(_.constant(2))({ 'a': 1 }); 2171 2172 assert.deepEqual(args, [undefined, 'b', { 'a': 1 }]); 2173 }); 2174 2175 QUnit.test('should not mutate values', function(assert) { 2176 assert.expect(2); 2177 2178 var object = { 'a': { 'b': 2, 'c': 3 } }, 2179 actual = fp.updateWith(Object)('d.e')(_.constant(4))(object); 2180 2181 assert.deepEqual(object, { 'a': { 'b': 2, 'c': 3 } }); 2182 assert.deepEqual(actual, { 'a': { 'b': 2, 'c': 3 }, 'd': { 'e': 4 } }); 2183 }); 2184 }()); 2185 2186 /*--------------------------------------------------------------------------*/ 2187 2188 QUnit.module('fp.unset'); 2189 2190 (function() { 2191 QUnit.test('should not mutate values', function(assert) { 2192 assert.expect(2); 2193 2194 var object = { 'a': { 'b': 2, 'c': 3 } }, 2195 actual = fp.unset('a.b')(object); 2196 2197 assert.deepEqual(object, { 'a': { 'b': 2, 'c': 3 } }); 2198 assert.deepEqual(actual, { 'a': { 'c': 3 } }); 2199 }); 2200 }()); 2201 2202 /*--------------------------------------------------------------------------*/ 2203 2204 QUnit.module('fp.xorBy'); 2205 2206 (function() { 2207 QUnit.test('should have an argument order of `iteratee`, `array`, then `other`', function(assert) { 2208 assert.expect(1); 2209 2210 var actual = fp.xorBy(Math.floor, [2.1, 1.2], [2.3, 3.4]); 2211 assert.deepEqual(actual, [1.2, 3.4]); 2212 }); 2213 2214 QUnit.test('should provide the correct `iteratee` arguments', function(assert) { 2215 assert.expect(1); 2216 2217 var args; 2218 2219 fp.xorBy(function() { 2220 args || (args = slice.call(arguments)); 2221 })([2.1, 1.2], [2.3, 3.4]); 2222 2223 assert.deepEqual(args, [2.3]); 2224 }); 2225 }()); 2226 2227 /*--------------------------------------------------------------------------*/ 2228 2229 QUnit.module('fp.xorWith'); 2230 2231 (function() { 2232 QUnit.test('should have an argument order of `comparator`, `array`, then `values`', function(assert) { 2233 assert.expect(1); 2234 2235 var actual = fp.xorWith(fp.eq)([2, 1])([2, 3]); 2236 assert.deepEqual(actual, [1, 3]); 2237 }); 2238 }()); 2239 2240 /*--------------------------------------------------------------------------*/ 2241 2242 QUnit.module('with methods'); 2243 2244 _.each(['differenceWith', 'intersectionWith', 'xorWith'], function(methodName) { 2245 var func = fp[methodName]; 2246 2247 QUnit.test('`fp.' + methodName + '` should provide the correct `comparator` arguments', function(assert) { 2248 assert.expect(1); 2249 2250 var args; 2251 2252 func(function() { 2253 args || (args = slice.call(arguments)); 2254 })([2, 1])([2, 3]); 2255 2256 assert.deepEqual(args, [2, 2]); 2257 }); 2258 }); 2259 2260 /*--------------------------------------------------------------------------*/ 2261 2262 QUnit.module('fp.zip'); 2263 2264 (function() { 2265 QUnit.test('should zip together two arrays', function(assert) { 2266 assert.expect(1); 2267 2268 assert.deepEqual(fp.zip([1, 2])([3, 4]), [[1, 3], [2, 4]]); 2269 }); 2270 }()); 2271 2272 /*--------------------------------------------------------------------------*/ 2273 2274 QUnit.module('fp.zipAll'); 2275 2276 (function() { 2277 QUnit.test('should zip together an array of arrays', function(assert) { 2278 assert.expect(1); 2279 2280 assert.deepEqual(fp.zipAll([[1, 2], [3, 4], [5, 6]]), [[1, 3, 5], [2, 4, 6]]); 2281 }); 2282 }()); 2283 2284 /*--------------------------------------------------------------------------*/ 2285 2286 QUnit.module('fp.zipObject'); 2287 2288 (function() { 2289 QUnit.test('should zip together key/value arrays into an object', function(assert) { 2290 assert.expect(1); 2291 2292 assert.deepEqual(fp.zipObject(['a', 'b'])([1, 2]), { 'a': 1, 'b': 2 }); 2293 }); 2294 }()); 2295 2296 /*--------------------------------------------------------------------------*/ 2297 2298 QUnit.module('fp.zipWith'); 2299 2300 (function() { 2301 QUnit.test('should zip arrays combining grouped elements with `iteratee`', function(assert) { 2302 assert.expect(1); 2303 2304 var array1 = [1, 2, 3], 2305 array2 = [4, 5, 6], 2306 actual = fp.zipWith(add)(array1)(array2); 2307 2308 assert.deepEqual(actual, [5, 7, 9]); 2309 }); 2310 }()); 2311 2312 /*--------------------------------------------------------------------------*/ 2313 2314 QUnit.config.asyncRetries = 10; 2315 QUnit.config.hidepassed = true; 2316 2317 if (!document) { 2318 QUnit.config.noglobals = true; 2319 QUnit.load(); 2320 QUnit.start(); 2321 } 2322}.call(this)); 2323