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