Built motion from commit fd239ea.|0.0.31
[motion.git] / public / bower_components / lodash / test / test-fp.js
1 ;(function() {
2
3   /** Used as a safe reference for `undefined` in pre-ES5 environments. */
4   var undefined;
5
6   /** Used as the size to cover large array optimizations. */
7   var LARGE_ARRAY_SIZE = 200;
8
9   /** Used as a reference to the global object. */
10   var root = (typeof global == 'object' && global) || this;
11
12   /** Used for native method references. */
13   var arrayProto = Array.prototype;
14
15   /** Method and object shortcuts. */
16   var phantom = root.phantom,
17       amd = root.define && define.amd,
18       document = !phantom && root.document,
19       noop = function() {},
20       slice = arrayProto.slice,
21       WeakMap = root.WeakMap;
22
23   /*--------------------------------------------------------------------------*/
24
25   /** Use a single "load" function. */
26   var load = (!amd && typeof require == 'function')
27     ? require
28     : noop;
29
30   /** The unit testing framework. */
31   var QUnit = root.QUnit || (root.QUnit = (
32     QUnit = load('../node_modules/qunitjs/qunit/qunit.js') || root.QUnit,
33     QUnit = QUnit.QUnit || QUnit
34   ));
35
36   /** Load stable Lodash and QUnit Extras. */
37   var _ = root._ || load('../lodash.js');
38   if (_) {
39     _ = _.runInContext(root);
40   }
41   var QUnitExtras = load('../node_modules/qunit-extras/qunit-extras.js');
42   if (QUnitExtras) {
43     QUnitExtras.runInContext(root);
44   }
45
46   var convert = root.fp || load('../lib/fp/convert.js'),
47       mapping = root.mapping || load('../lib/fp/mapping.js'),
48       fp = convert(_.runInContext());
49
50   /*--------------------------------------------------------------------------*/
51
52   /**
53    * Skips a given number of tests with a passing result.
54    *
55    * @private
56    * @param {Object} assert The QUnit assert object.
57    * @param {number} [count=1] The number of tests to skip.
58    */
59   function skipTest(assert, count) {
60     count || (count = 1);
61     while (count--) {
62       assert.ok(true, 'test skipped');
63     }
64   }
65
66   /*--------------------------------------------------------------------------*/
67
68   QUnit.module('method aliases');
69
70   (function() {
71     QUnit.test('should have correct aliases', function(assert) {
72       assert.expect(1);
73
74       var actual = _.transform(mapping.aliasMap, function(result, aliases, methodName) {
75         var func = fp[methodName];
76         _.each(aliases, function(alias) {
77           result.push([alias, fp[alias] === func]);
78         });
79       }, []);
80
81       assert.deepEqual(_.reject(actual, 1), []);
82     });
83   }());
84
85   /*--------------------------------------------------------------------------*/
86
87   QUnit.module('method ary caps');
88
89   (function() {
90     QUnit.test('should have a cap of 1', function(assert) {
91       assert.expect(1);
92
93       var funcMethods = [
94         'curry', 'iteratee', 'memoize', 'over', 'overEvery', 'overSome',
95         'method', 'methodOf', 'restParam', 'runInContext'
96       ];
97
98       var exceptions = funcMethods.concat('mixin', 'template'),
99           expected = _.map(mapping.aryMethodMap[1], _.constant(true));
100
101       var actual = _.map(mapping.aryMethodMap[1], function(methodName) {
102         var arg = _.includes(funcMethods, methodName) ? _.noop : 1,
103             result = _.attempt(function() { return fp[methodName](arg); });
104
105         if (_.includes(exceptions, methodName)
106               ? typeof result == 'function'
107               : typeof result != 'function'
108             ) {
109           return true;
110         }
111         console.log(methodName, result);
112         return false;
113       });
114
115       assert.deepEqual(actual, expected);
116     });
117
118     QUnit.test('should have a cap of 2', function(assert) {
119       assert.expect(1);
120
121       var funcMethods = [
122         'after', 'ary', 'before', 'bind', 'bindKey', 'cloneDeepWith', 'cloneWith',
123         'curryN', 'debounce', 'delay', 'overArgs', 'rearg', 'throttle', 'wrap'
124       ];
125
126       var exceptions = _.difference(funcMethods.concat('matchesProperty'), ['cloneDeepWith', 'cloneWith', 'delay']),
127           expected = _.map(mapping.aryMethodMap[2], _.constant(true));
128
129       var actual = _.map(mapping.aryMethodMap[2], function(methodName) {
130         var args = _.includes(funcMethods, methodName) ? [methodName == 'curryN' ? 1 : _.noop, _.noop] : [1, []],
131             result = _.attempt(function() { return fp[methodName](args[0])(args[1]); });
132
133         if (_.includes(exceptions, methodName)
134               ? typeof result == 'function'
135               : typeof result != 'function'
136             ) {
137           return true;
138         }
139         console.log(methodName, result);
140         return false;
141       });
142
143       assert.deepEqual(actual, expected);
144     });
145
146     QUnit.test('should have a cap of 3', function(assert) {
147       assert.expect(1);
148
149       var funcMethods = [
150         'assignWith', 'extendWith', 'isEqualWith', 'isMatchWith', 'omitBy',
151         'pickBy', 'reduce', 'reduceRight', 'transform', 'zipWith'
152       ];
153
154       var expected = _.map(mapping.aryMethodMap[3], _.constant(true));
155
156       var actual = _.map(mapping.aryMethodMap[3], function(methodName) {
157         var args = _.includes(funcMethods, methodName) ? [_.noop, 0, 1] : [0, 1, []],
158             result = _.attempt(function() { return fp[methodName](args[0])(args[1])(args[2]); });
159
160         if (typeof result != 'function') {
161           return true;
162         }
163         console.log(methodName, result);
164         return false;
165       });
166
167       assert.deepEqual(actual, expected);
168     });
169   }());
170
171   /*--------------------------------------------------------------------------*/
172
173   QUnit.module('methods that use `indexOf`');
174
175   (function() {
176     QUnit.test('should work with `fp.indexOf`', function(assert) {
177       assert.expect(10);
178
179       var array = ['a', 'b', 'c'],
180           other = ['b', 'b', 'd'],
181           object = { 'a': 1, 'b': 2, 'c': 2 },
182           actual = fp.difference(array, other);
183
184       assert.deepEqual(actual, ['a', 'c'], 'fp.difference');
185
186       actual = fp.includes('b', array);
187       assert.strictEqual(actual, true, 'fp.includes');
188
189       actual = fp.intersection(other, array);
190       assert.deepEqual(actual, ['b'], 'fp.intersection');
191
192       actual = fp.omit(other, object);
193       assert.deepEqual(actual, { 'a': 1, 'c': 2 }, 'fp.omit');
194
195       actual = fp.union(other, array);
196       assert.deepEqual(actual, ['a', 'b', 'c', 'd'], 'fp.union');
197
198       actual = fp.uniq(other);
199       assert.deepEqual(actual, ['b', 'd'], 'fp.uniq');
200
201       actual = fp.uniqBy(_.identity, other);
202       assert.deepEqual(actual, ['b', 'd'], 'fp.uniqBy');
203
204       actual = fp.without('b', array);
205       assert.deepEqual(actual, ['a', 'c'], 'fp.without');
206
207       actual = fp.xor(other, array);
208       assert.deepEqual(actual, ['a', 'c', 'd'], 'fp.xor');
209
210       actual = fp.pull('b', array);
211       assert.deepEqual(actual, ['a', 'c'], 'fp.pull');
212     });
213   }());
214
215   /*--------------------------------------------------------------------------*/
216
217   QUnit.module('cherry-picked methods');
218
219   (function() {
220     QUnit.test('should provide the correct `iteratee` arguments', function(assert) {
221       assert.expect(4);
222
223       if (!document) {
224         var args,
225             array = [1, 2, 3],
226             object = { 'a': 1, 'b': 2 },
227             isFIFO = _.keys(object)[0] == 'a',
228             map = convert('map', _.map),
229             reduce = convert('reduce', _.reduce);
230
231         map(function() {
232           args || (args = slice.call(arguments));
233         })(array);
234
235         assert.deepEqual(args, [1]);
236
237         args = undefined;
238         map(function() {
239           args || (args = slice.call(arguments));
240         })(object);
241
242         assert.deepEqual(args, isFIFO ? [1] : [2]);
243
244         args = undefined;
245         reduce(function() {
246           args || (args = slice.call(arguments));
247         })(0, array);
248
249         assert.deepEqual(args, [0, 1]);
250
251         args = undefined;
252         reduce(function() {
253           args || (args = slice.call(arguments));
254         })(0, object);
255
256         assert.deepEqual(args, isFIFO ? [0, 1] : [0, 2]);
257       }
258       else {
259         skipTest(assert, 4);
260       }
261     });
262
263     QUnit.test('should not support shortcut fusion', function(assert) {
264       assert.expect(3);
265
266       if (!document) {
267         var array = fp.range(0, LARGE_ARRAY_SIZE),
268             filterCount = 0,
269             mapCount = 0;
270
271         var iteratee = function(value) {
272           mapCount++;
273           return value * value;
274         };
275
276         var predicate = function(value) {
277           filterCount++;
278           return value % 2 == 0;
279         };
280
281         var map1 = convert('map', _.map),
282             filter1 = convert('filter', _.filter),
283             take1 = convert('take', _.take);
284
285         var filter2 = filter1(predicate),
286             map2 = map1(iteratee),
287             take2 = take1(2);
288
289         var combined = fp.flow(map2, filter2, fp.compact, take2);
290
291         assert.deepEqual(combined(array), [4, 16]);
292         assert.strictEqual(filterCount, 200, 'filterCount');
293         assert.strictEqual(mapCount, 200, 'mapCount');
294       }
295       else {
296         skipTest(assert, 3);
297       }
298     });
299   }());
300
301   /*--------------------------------------------------------------------------*/
302
303   QUnit.module('curry methods');
304
305   _.each(['curry', 'curryRight'], function(methodName) {
306     var func = fp[methodName];
307
308     QUnit.test('`_.' + methodName + '` should only accept a `func` param', function(assert) {
309       assert.expect(1);
310
311       assert.raises(function() { func(1, _.noop); }, TypeError);
312     });
313   });
314
315   /*--------------------------------------------------------------------------*/
316
317   QUnit.module('curryN methods');
318
319   _.each(['curryN', 'curryRightN'], function(methodName) {
320     var func = fp[methodName];
321
322     QUnit.test('`_.' + methodName + '` accept an `arity` param', function(assert) {
323       assert.expect(1);
324
325       var actual = func(1, function(a, b) { return [a, b]; })('a');
326       assert.deepEqual(actual, ['a', undefined]);
327     });
328   });
329
330   /*--------------------------------------------------------------------------*/
331
332   QUnit.module('fp.difference');
333
334   (function() {
335     QUnit.test('should return the elements of the first array not included in the second array', function(assert) {
336       assert.expect(1);
337
338       assert.deepEqual(fp.difference([1, 2])([2, 3]), [1]);
339     });
340   }());
341
342   /*--------------------------------------------------------------------------*/
343
344   QUnit.module('fp.fill');
345
346   (function() {
347     QUnit.test('should have an argument order of `start`, `end`, then `value`', function(assert) {
348       assert.expect(1);
349
350       var array = [1, 2, 3];
351       assert.deepEqual(fp.fill(1)(2)('*')(array), [1, '*', 3]);
352     });
353   }());
354
355   /*--------------------------------------------------------------------------*/
356
357   QUnit.module('fp.flow and fp.flowRight');
358
359   _.each(['flow', 'flowRight'], function(methodName, index) {
360     var func = fp[methodName],
361         isFlow = methodName == 'flow';
362
363     QUnit.test('`fp.' + methodName + '` should support shortcut fusion', function(assert) {
364       assert.expect(6);
365
366       var filterCount,
367           mapCount,
368           array = fp.range(0, LARGE_ARRAY_SIZE);
369
370       var iteratee = function(value) {
371         mapCount++;
372         return value * value;
373       };
374
375       var predicate = function(value) {
376         filterCount++;
377         return value % 2 == 0;
378       };
379
380       var filter = fp.filter(predicate),
381           map = fp.map(iteratee),
382           take = fp.take(2);
383
384       _.times(2, function(index) {
385         var combined = isFlow
386           ? func(map, filter, fp.compact, take)
387           : func(take, fp.compact, filter, map);
388
389         filterCount = mapCount = 0;
390
391         if (WeakMap && WeakMap.name) {
392           assert.deepEqual(combined(array), [4, 16]);
393           assert.strictEqual(filterCount, 5, 'filterCount');
394           assert.strictEqual(mapCount, 5, 'mapCount');
395         }
396         else {
397           skipTest(assert, 3);
398         }
399       });
400     });
401   });
402
403   /*--------------------------------------------------------------------------*/
404
405   QUnit.module('fp.inRange');
406
407   (function() {
408     QUnit.test('should have an argument order of `start`, `end`, then `value`', function(assert) {
409       assert.expect(1);
410
411       assert.strictEqual(fp.inRange(2)(4)(3), true);
412     });
413   }());
414
415   /*--------------------------------------------------------------------------*/
416
417   QUnit.module('fp.iteratee');
418
419   (function() {
420     QUnit.test('should return a iteratee with capped params', function(assert) {
421       assert.expect(1);
422
423       var func = fp.iteratee(function(a, b, c) { return [a, b, c]; }, undefined, 3);
424       assert.deepEqual(func(1, 2, 3), [1, undefined, undefined]);
425     });
426
427     QUnit.test('should convert by name', function(assert) {
428       assert.expect(1);
429
430       if (!document) {
431         var iteratee = convert('iteratee', _.iteratee),
432             func = iteratee(function(a, b, c) { return [a, b, c]; }, undefined, 3);
433
434         assert.deepEqual(func(1, 2, 3), [1, undefined, undefined]);
435       }
436       else {
437         skipTest(assert);
438       }
439     });
440   }());
441
442   /*--------------------------------------------------------------------------*/
443
444   QUnit.module('fp.maxBy and fp.minBy');
445
446   _.each(['maxBy', 'minBy'], function(methodName, index) {
447     var array = [1, 2, 3],
448         func = fp[methodName],
449         isMax = !index;
450
451     QUnit.test('`fp.' + methodName + '` should work with an `iteratee` argument', function(assert) {
452       assert.expect(1);
453
454       var actual = func(function(num) {
455         return -num;
456       })(array);
457
458       assert.strictEqual(actual, isMax ? 1 : 3);
459     });
460
461     QUnit.test('`fp.' + methodName + '` should provide the correct `iteratee` arguments', function(assert) {
462       assert.expect(1);
463
464       var args;
465
466       func(function() {
467         args || (args = slice.call(arguments));
468       })(array);
469
470       assert.deepEqual(args, [1]);
471     });
472   });
473
474   /*--------------------------------------------------------------------------*/
475
476   QUnit.module('fp.mixin');
477
478   (function() {
479     var source = { 'a': _.noop };
480
481     QUnit.test('should mixin static methods but not prototype methods', function(assert) {
482       assert.expect(2);
483
484       fp.mixin(source);
485
486       assert.strictEqual(typeof fp.a, 'function');
487       assert.notOk('a' in fp.prototype);
488
489       delete fp.a;
490       delete fp.prototype.a;
491     });
492
493     QUnit.test('should not assign inherited `source` methods', function(assert) {
494       assert.expect(2);
495
496       function Foo() {}
497       Foo.prototype.a = _.noop;
498       fp.mixin(new Foo);
499
500       assert.notOk('a' in fp);
501       assert.notOk('a' in fp.prototype);
502
503       delete fp.a;
504       delete fp.prototype.a;
505     });
506
507     QUnit.test('should not remove existing prototype methods', function(assert) {
508       assert.expect(2);
509
510       var each1 = fp.each,
511           each2 = fp.prototype.each;
512
513       fp.mixin({ 'each': source.a });
514
515       assert.strictEqual(fp.each, source.a);
516       assert.strictEqual(fp.prototype.each, each2);
517
518       fp.each = each1;
519       fp.prototype.each = each2;
520     });
521
522     QUnit.test('should not export to the global when `source` is not an object', function(assert) {
523       assert.expect(2);
524
525       var props = _.without(_.keys(_), '_');
526
527       _.times(2, function(index) {
528         fp.mixin.apply(fp, index ? [1] : []);
529
530         assert.ok(_.every(props, function(key) {
531           return root[key] !== fp[key];
532         }));
533
534         _.each(props, function(key) {
535           if (root[key] === fp[key]) {
536             delete root[key];
537           }
538         });
539       });
540     });
541
542     QUnit.test('should convert by name', function(assert) {
543       assert.expect(3);
544
545       if (!document) {
546         var object = { 'mixin': convert('mixin', _.mixin) };
547
548         function Foo() {}
549         Foo.mixin = object.mixin;
550         Foo.mixin(source);
551
552         assert.strictEqual(typeof Foo.a, 'function');
553         assert.notOk('a' in Foo.prototype);
554
555         object.mixin(source);
556         assert.strictEqual(typeof object.a, 'function');
557       }
558       else {
559         skipTest(assert, 3);
560       }
561     });
562   }());
563
564   /*--------------------------------------------------------------------------*/
565
566   QUnit.module('fp.random');
567
568   (function() {
569     var array = Array(1000);
570
571     QUnit.test('should support a `min` and `max` argument', function(assert) {
572       assert.expect(1);
573
574       var min = 5,
575           max = 10;
576
577       assert.ok(_.some(array, function() {
578         var result = fp.random(min)(max);
579         return result >= min && result <= max;
580       }));
581     });
582   }());
583
584   /*--------------------------------------------------------------------------*/
585
586   QUnit.module('fp.range');
587
588   (function() {
589     QUnit.test('should have an argument order of `start` then `end`', function(assert) {
590       assert.expect(1);
591
592       assert.deepEqual(fp.range(1)(4), [1, 2, 3]);
593     });
594   }());
595
596   /*--------------------------------------------------------------------------*/
597
598   QUnit.module('reduce methods');
599
600   _.each(['reduce', 'reduceRight'], function(methodName) {
601     var func = fp[methodName],
602         isReduce = methodName == 'reduce';
603
604     QUnit.test('`_.' + methodName + '` should provide the correct `iteratee` arguments when iterating an array', function(assert) {
605       assert.expect(1);
606
607       var args,
608           array = [1, 2, 3];
609
610       func(function() {
611         args || (args = slice.call(arguments));
612       })(0, array);
613
614       assert.deepEqual(args, isReduce ? [0, 1] : [0, 3]);
615     });
616
617     QUnit.test('`_.' + methodName + '` should provide the correct `iteratee` arguments when iterating an object', function(assert) {
618       assert.expect(1);
619
620       var args,
621           object = { 'a': 1, 'b': 2 },
622           isFIFO = _.keys(object)[0] == 'a';
623
624       var expected = isFIFO
625         ? (isReduce ? [0, 1] : [0, 2])
626         : (isReduce ? [0, 2] : [0, 1]);
627
628       func(function() {
629         args || (args = slice.call(arguments));
630       })(0, object);
631
632       assert.deepEqual(args, expected);
633     });
634   });
635
636   /*--------------------------------------------------------------------------*/
637
638   QUnit.module('fp.runInContext');
639
640   (function() {
641     QUnit.test('should return a converted lodash instance', function(assert) {
642       assert.expect(1);
643
644       assert.strictEqual(typeof fp.runInContext({}).curryN, 'function');
645     });
646
647     QUnit.test('should convert by name', function(assert) {
648       assert.expect(1);
649
650       if (!document) {
651         var runInContext = convert('runInContext', _.runInContext);
652         assert.strictEqual(typeof runInContext({}).curryN, 'function');
653       }
654       else {
655         skipTest(assert);
656       }
657     });
658   }());
659
660   /*--------------------------------------------------------------------------*/
661
662   QUnit.module('fp.uniqBy');
663
664   (function() {
665     var objects = [{ 'a': 2 }, { 'a': 3 }, { 'a': 1 }, { 'a': 2 }, { 'a': 3 }, { 'a': 1 }];
666
667     QUnit.test('should work with an `iteratee` argument', function(assert) {
668       assert.expect(1);
669
670       var expected = objects.slice(0, 3);
671
672       var actual = fp.uniqBy(function(object) {
673         return object.a;
674       })(objects);
675
676       assert.deepEqual(actual, expected);
677     });
678
679     QUnit.test('should provide the correct `iteratee` arguments', function(assert) {
680       assert.expect(1);
681
682       var args;
683
684       fp.uniqBy(function() {
685         args || (args = slice.call(arguments));
686       })(objects);
687
688       assert.deepEqual(args, [objects[0]]);
689     });
690   }());
691
692   /*--------------------------------------------------------------------------*/
693
694   QUnit.module('fp.zip');
695
696   (function() {
697     QUnit.test('should zip together two arrays', function(assert) {
698       assert.expect(1);
699
700       assert.deepEqual(fp.zip([1, 2], [3, 4]), [[1, 3], [2, 4]]);
701     });
702   }());
703
704   /*--------------------------------------------------------------------------*/
705
706   QUnit.module('fp.zipObject');
707
708   (function() {
709     QUnit.test('should zip together key/value arrays into an object', function(assert) {
710       assert.expect(1);
711
712       assert.deepEqual(fp.zipObject(['a', 'b'], [1, 2]), { 'a': 1, 'b': 2 });
713     });
714   }());
715
716   /*--------------------------------------------------------------------------*/
717
718   QUnit.module('mutation methods');
719
720   (function() {
721     var array = [1, 2, 3],
722         object = { 'a': 1 },
723         deepObject = { 'a': { 'b': 2, 'c': 3 } };
724
725     QUnit.test('should not mutate values', function(assert) {
726       assert.expect(32);
727
728       function Foo() {}
729       Foo.prototype = { 'b': 2 };
730
731       var value = _.clone(object),
732           actual = fp.assign({ 'b': 2 }, value);
733
734       assert.deepEqual(value, object, 'fp.assign');
735       assert.deepEqual(actual, { 'a': 1, 'b': 2 }, 'fp.assign');
736
737       value = _.clone(object);
738       actual = fp.assignWith(function(objValue, srcValue) {
739         return srcValue;
740       }, { 'b': 2 }, value);
741
742       assert.deepEqual(value, object, 'fp.assignWith');
743       assert.deepEqual(actual, { 'a': 1, 'b': 2 }, 'fp.assignWith');
744
745       value = _.clone(object);
746       actual = fp.defaults({ 'a': 2, 'b': 2 }, value);
747
748       assert.deepEqual(value, object, 'fp.defaults');
749       assert.deepEqual(actual, { 'a': 1, 'b': 2 }, 'fp.defaults');
750
751       value = _.clone(object);
752       value.b = { 'c': 1 };
753       actual = fp.defaultsDeep({ 'b': { 'c': 2, 'd': 2 } }, value);
754
755       assert.deepEqual(value, { 'a': 1, 'b': { 'c': 1 } } , 'fp.defaultsDeep');
756       assert.deepEqual(actual, { 'a': 1, 'b': { 'c': 1, 'd': 2 } }, 'fp.defaultsDeep');
757
758       value = _.clone(object);
759       actual = fp.extend(new Foo, value);
760
761       assert.deepEqual(value, object, 'fp.extend');
762       assert.deepEqual(actual, { 'a': 1, 'b': 2 }, 'fp.extend');
763
764       value = _.clone(object);
765       actual = fp.extendWith(function(objValue, srcValue) {
766         return srcValue;
767       }, new Foo, value);
768
769       assert.deepEqual(value, object, 'fp.extendWith');
770       assert.deepEqual(actual, { 'a': 1, 'b': 2 }, 'fp.extendWith');
771
772       value = _.clone(array);
773       actual = fp.fill(1, 2, '*', value);
774
775       assert.deepEqual(value, array, 'fp.fill');
776       assert.deepEqual(actual, [1, '*', 3], 'fp.fill');
777
778       value = { 'a': { 'b': 2 } };
779       actual = fp.merge({ 'a': { 'c': 3 } }, value);
780
781       assert.deepEqual(value, { 'a': { 'b': 2 } }, 'fp.merge');
782       assert.deepEqual(actual, { 'a': { 'b': 2, 'c': 3 } }, 'fp.merge');
783
784       value = { 'a': [1] };
785       actual = fp.mergeWith(function(objValue, srcValue) {
786         if (_.isArray(objValue)) {
787           return objValue.concat(srcValue);
788         }
789       }, { 'a': [2, 3] }, value);
790
791       assert.deepEqual(value, { 'a': [1] }, 'fp.mergeWith');
792       assert.deepEqual(actual, { 'a': [1, 2, 3] }, 'fp.mergeWith');
793
794       value = _.clone(array);
795       actual = fp.pull(2, value);
796
797       assert.deepEqual(value, array, 'fp.pull');
798       assert.deepEqual(actual, [1, 3], 'fp.pull');
799
800       value = _.clone(array);
801       actual = fp.pullAll([1, 3], value);
802
803       assert.deepEqual(value, array, 'fp.pullAll');
804       assert.deepEqual(actual, [2], 'fp.pullAll');
805
806       value = _.clone(array);
807       actual = fp.pullAt([0, 2], value);
808
809       assert.deepEqual(value, array, 'fp.pullAt');
810       assert.deepEqual(actual, [2], 'fp.pullAt');
811
812       value = _.clone(array);
813       actual = fp.remove(function(value) {
814         return value === 2;
815       }, value);
816
817       assert.deepEqual(value, array, 'fp.remove');
818       assert.deepEqual(actual, [1, 3], 'fp.remove');
819
820       value = _.clone(array);
821       actual = fp.reverse(value);
822
823       assert.deepEqual(value, array, 'fp.reverse');
824       assert.deepEqual(actual, [3, 2, 1], 'fp.reverse');
825
826       value = _.cloneDeep(deepObject);
827       actual = fp.set(3, 'a.b', value);
828
829       assert.deepEqual(value, deepObject, 'fp.set');
830       assert.deepEqual(actual, { 'a': { 'b': 3, 'c': 3 } }, 'fp.set');
831
832       value = _.cloneDeep(deepObject);
833       actual = fp.setWith(Object, 4, 'd.e', value);
834
835       assert.deepEqual(value, deepObject, 'fp.setWith');
836       assert.deepEqual(actual, { 'a': { 'b': 2, 'c': 3 }, 'd': { 'e': 4 } }, 'fp.setWith');
837     });
838   }());
839
840   /*--------------------------------------------------------------------------*/
841
842   QUnit.module('with methods');
843
844   (function() {
845     var array = [1, 2, 3],
846         object = { 'a': 1 };
847
848     QUnit.test('should provide the correct `customizer` arguments', function(assert) {
849       assert.expect(3);
850
851       var args,
852           value = _.clone(object);
853
854       var actual = fp.assignWith(function(objValue, srcValue) {
855         args || (args = _.map(arguments, _.cloneDeep));
856         return srcValue;
857       }, { 'b': 2 }, value);
858
859       assert.deepEqual(args, [undefined, 2, 'b', { 'a': 1 }, { 'b': 2 }], 'fp.assignWith');
860
861       args = undefined;
862       value = _.clone(object);
863       actual = fp.extendWith(function(objValue, srcValue) {
864         args || (args = _.map(arguments, _.cloneDeep));
865         return srcValue;
866       }, { 'b': 2 }, value);
867
868       assert.deepEqual(args, [undefined, 2, 'b', { 'a': 1 }, { 'b': 2 }], 'fp.extendWith');
869
870       var stack = { '__data__': { 'array': [], 'map': null } },
871           expected = [[1], [2, 3], 'a', { 'a': [ 1 ] }, { 'a': [2, 3] }, stack];
872
873       args = undefined;
874       value = { 'a': [1] };
875       actual = fp.mergeWith(function(objValue, srcValue) {
876         args || (args = _.map(arguments, _.cloneDeep));
877         if (_.isArray(objValue)) {
878           return objValue.concat(srcValue);
879         }
880       }, { 'a': [2, 3] }, value);
881
882       args[5] = _.omitBy(args[5], _.isFunction);
883       assert.deepEqual(args, expected, 'fp.mergeWith');
884     });
885   }());
886
887   /*--------------------------------------------------------------------------*/
888
889   QUnit.config.asyncRetries = 10;
890   QUnit.config.hidepassed = true;
891
892   if (!document) {
893     QUnit.config.noglobals = true;
894     QUnit.load();
895   }
896 }.call(this));