3 /** Used as a safe reference for `undefined` in pre-ES5 environments. */
6 /** Used as the size to cover large array optimizations. */
7 var LARGE_ARRAY_SIZE = 200;
9 /** Used as a reference to the global object. */
10 var root = (typeof global == 'object' && global) || this;
12 /** Used for native method references. */
13 var arrayProto = Array.prototype;
15 /** Method and object shortcuts. */
16 var phantom = root.phantom,
17 argv = root.process && process.argv,
18 document = !phantom && root.document,
19 slice = arrayProto.slice,
20 WeakMap = root.WeakMap;
23 var add = function(x, y) { return x + y; },
24 isEven = function(n) { return n % 2 == 0; },
25 square = function(n) { return n * n; };
27 // Leak to avoid sporadic `noglobals` fails on Edge in Sauce Labs.
28 root.msWDfn = undefined;
30 /*--------------------------------------------------------------------------*/
32 /** Load QUnit and extras. */
33 var QUnit = root.QUnit || require('qunit-extras');
35 /** Load stable Lodash. */
36 var _ = root._ || require('../lodash.js');
38 var convert = (function() {
39 var baseConvert = root.fp || require('../fp/_baseConvert.js');
41 return function(name, func, options) {
42 return baseConvert(_, name, func, options);
45 return function(name, func, options) {
46 if (typeof name == 'function') {
51 return name === undefined
52 ? baseConvert(func, options)
53 : baseConvert(_.runInContext(), options)[name];
57 var allFalseOptions = {
66 ? (fp = _.noConflict(), _ = root._, fp)
67 : convert(_.runInContext());
69 var mapping = root.mapping || require('../fp/_mapping.js');
71 /*--------------------------------------------------------------------------*/
74 * Skips a given number of tests with a passing result.
77 * @param {Object} assert The QUnit assert object.
78 * @param {number} [count=1] The number of tests to skip.
80 function skipAssert(assert, count) {
83 assert.ok(true, 'test skipped');
87 /*--------------------------------------------------------------------------*/
90 console.log('Running lodash/fp tests.');
93 QUnit.module('convert module');
96 QUnit.test('should work with `name` and `func`', function(assert) {
99 var array = [1, 2, 3, 4],
100 remove = convert('remove', _.remove),
101 actual = remove(isEven)(array);
103 assert.deepEqual(array, [1, 2, 3, 4]);
104 assert.deepEqual(actual, [1, 3]);
107 QUnit.test('should work with `name`, `func`, and `options`', function(assert) {
110 var array = [1, 2, 3, 4],
111 remove = convert('remove', _.remove, allFalseOptions);
113 var actual = remove(array, function(n, index) {
114 return isEven(index);
117 assert.deepEqual(array, [2, 4]);
118 assert.deepEqual(actual, [1, 3]);
119 assert.deepEqual(remove(), []);
122 QUnit.test('should work with an object', function(assert) {
126 var array = [1, 2, 3, 4],
127 lodash = convert({ 'remove': _.remove }),
128 actual = lodash.remove(isEven)(array);
130 assert.deepEqual(array, [1, 2, 3, 4]);
131 assert.deepEqual(actual, [1, 3]);
134 skipAssert(assert, 2);
138 QUnit.test('should work with an object and `options`', function(assert) {
142 var array = [1, 2, 3, 4],
143 lodash = convert({ 'remove': _.remove }, allFalseOptions);
145 var actual = lodash.remove(array, function(n, index) {
146 return isEven(index);
149 assert.deepEqual(array, [2, 4]);
150 assert.deepEqual(actual, [1, 3]);
151 assert.deepEqual(lodash.remove(), []);
154 skipAssert(assert, 3);
158 QUnit.test('should work with lodash and `options`', function(assert) {
161 var array = [1, 2, 3, 4],
162 lodash = convert(_.runInContext(), allFalseOptions);
164 var actual = lodash.remove(array, function(n, index) {
165 return isEven(index);
168 assert.deepEqual(array, [2, 4]);
169 assert.deepEqual(actual, [1, 3]);
170 assert.deepEqual(lodash.remove(), []);
173 QUnit.test('should work with `runInContext` and `options`', function(assert) {
176 var array = [1, 2, 3, 4],
177 runInContext = convert('runInContext', _.runInContext, allFalseOptions),
178 lodash = runInContext();
180 var actual = lodash.remove(array, function(n, index) {
181 return isEven(index);
184 assert.deepEqual(array, [2, 4]);
185 assert.deepEqual(actual, [1, 3]);
186 assert.deepEqual(lodash.remove(), []);
189 QUnit.test('should accept a variety of options', function(assert) {
192 var array = [1, 2, 3, 4],
193 value = _.clone(array),
194 remove = convert('remove', _.remove, { 'cap': false }),
195 actual = remove(function(n, index) { return isEven(index); })(value);
197 assert.deepEqual(value, [1, 2, 3, 4]);
198 assert.deepEqual(actual, [2, 4]);
200 remove = convert('remove', _.remove, { 'curry': false });
201 actual = remove(isEven);
203 assert.deepEqual(actual, []);
205 var trim = convert('trim', _.trim, { 'fixed': false });
206 assert.strictEqual(trim('_-abc-_', '_-'), 'abc');
208 value = _.clone(array);
209 remove = convert('remove', _.remove, { 'immutable': false });
210 actual = remove(isEven)(value);
212 assert.deepEqual(value, [1, 3]);
213 assert.deepEqual(actual, [2, 4]);
215 value = _.clone(array);
216 remove = convert('remove', _.remove, { 'rearg': false });
217 actual = remove(value)(isEven);
219 assert.deepEqual(value, [1, 2, 3, 4]);
220 assert.deepEqual(actual, [1, 3]);
223 QUnit.test('should respect the `cap` option', function(assert) {
226 var iteratee = convert('iteratee', _.iteratee, { 'cap': false });
228 var func = iteratee(function(a, b, c) {
232 assert.deepEqual(func(1, 2, 3), [1, 2, 3]);
235 QUnit.test('should respect the `rearg` option', function(assert) {
238 var add = convert('add', _.add, { 'rearg': true });
240 assert.strictEqual(add('2')('1'), '12');
243 QUnit.test('should only add a `placeholder` property if needed', function(assert) {
247 var methodNames = _.keys(mapping.placeholder),
248 expected = _.map(methodNames, _.constant(true));
250 var actual = _.map(methodNames, function(methodName) {
252 object[methodName] = _[methodName];
254 var lodash = convert(object);
255 return methodName in lodash;
258 assert.deepEqual(actual, expected);
260 var lodash = convert({ 'add': _.add });
261 assert.notOk('placeholder' in lodash);
264 skipAssert(assert, 2);
269 /*--------------------------------------------------------------------------*/
271 QUnit.module('method.convert');
274 QUnit.test('should exist on unconverted methods', function(assert) {
278 isArray = fp.isArray.convert({ 'curry': true });
280 assert.strictEqual(fp.isArray(array), true);
281 assert.strictEqual(isArray()(array), true);
285 /*--------------------------------------------------------------------------*/
287 QUnit.module('convert methods');
289 _.each(['fp.convert', 'method.convert'], function(methodName) {
290 var isFp = methodName == 'fp.convert',
291 func = isFp ? fp.convert : fp.remove.convert;
293 QUnit.test('`' + methodName + '` should work with an object', function(assert) {
296 var array = [1, 2, 3, 4],
297 lodash = func(allFalseOptions),
298 remove = isFp ? lodash.remove : lodash;
300 var actual = remove(array, function(n, index) {
301 return isEven(index);
304 assert.deepEqual(array, [2, 4]);
305 assert.deepEqual(actual, [1, 3]);
306 assert.deepEqual(remove(), []);
309 QUnit.test('`' + methodName + '` should extend existing configs', function(assert) {
312 var array = [1, 2, 3, 4],
313 lodash = func({ 'cap': false }),
314 remove = (isFp ? lodash.remove : lodash).convert({ 'rearg': false });
316 var actual = remove(array)(function(n, index) {
317 return isEven(index);
320 assert.deepEqual(array, [1, 2, 3, 4]);
321 assert.deepEqual(actual, [2, 4]);
325 /*--------------------------------------------------------------------------*/
327 QUnit.module('method arity checks');
330 QUnit.test('should wrap methods with an arity > `1`', function(assert) {
333 var methodNames = _.filter(_.functions(fp), function(methodName) {
334 return fp[methodName].length > 1;
337 assert.deepEqual(methodNames, []);
340 QUnit.test('should have >= arity of `aryMethod` designation', function(assert) {
343 _.times(4, function(index) {
344 var aryCap = index + 1;
346 var methodNames = _.filter(mapping.aryMethod[aryCap], function(methodName) {
347 var key = _.result(mapping.remap, methodName, methodName),
348 arity = _[key].length;
350 return arity != 0 && arity < aryCap;
353 assert.deepEqual(methodNames, [], '`aryMethod[' + aryCap + ']`');
358 /*--------------------------------------------------------------------------*/
360 QUnit.module('method aliases');
363 QUnit.test('should have correct aliases', function(assert) {
366 var actual = _.transform(mapping.aliasToReal, function(result, realName, alias) {
367 result.push([alias, fp[alias] === fp[realName]]);
370 assert.deepEqual(_.reject(actual, 1), []);
374 /*--------------------------------------------------------------------------*/
376 QUnit.module('method ary caps');
379 QUnit.test('should have a cap of 1', function(assert) {
383 'curry', 'iteratee', 'memoize', 'over', 'overEvery', 'overSome',
384 'method', 'methodOf', 'rest', 'runInContext'
387 var exceptions = funcMethods.concat('mixin', 'template'),
388 expected = _.map(mapping.aryMethod[1], _.constant(true));
390 var actual = _.map(mapping.aryMethod[1], function(methodName) {
391 var arg = _.includes(funcMethods, methodName) ? _.noop : 1,
392 result = _.attempt(function() { return fp[methodName](arg); });
394 if (_.includes(exceptions, methodName)
395 ? typeof result == 'function'
396 : typeof result != 'function'
400 console.log(methodName, result);
404 assert.deepEqual(actual, expected);
407 QUnit.test('should have a cap of 2', function(assert) {
411 'after', 'ary', 'before', 'bind', 'bindKey', 'curryN', 'debounce',
412 'delay', 'overArgs', 'partial', 'partialRight', 'rearg', 'throttle',
416 var exceptions = _.difference(funcMethods.concat('matchesProperty'), ['cloneDeepWith', 'cloneWith', 'delay']),
417 expected = _.map(mapping.aryMethod[2], _.constant(true));
419 var actual = _.map(mapping.aryMethod[2], function(methodName) {
420 var args = _.includes(funcMethods, methodName) ? [methodName == 'curryN' ? 1 : _.noop, _.noop] : [1, []],
421 result = _.attempt(function() { return fp[methodName](args[0])(args[1]); });
423 if (_.includes(exceptions, methodName)
424 ? typeof result == 'function'
425 : typeof result != 'function'
429 console.log(methodName, result);
433 assert.deepEqual(actual, expected);
436 QUnit.test('should have a cap of 3', function(assert) {
440 'assignWith', 'extendWith', 'isEqualWith', 'isMatchWith', 'reduce',
441 'reduceRight', 'transform', 'zipWith'
444 var expected = _.map(mapping.aryMethod[3], _.constant(true));
446 var actual = _.map(mapping.aryMethod[3], function(methodName) {
447 var args = _.includes(funcMethods, methodName) ? [_.noop, 0, 1] : [0, 1, []],
448 result = _.attempt(function() { return fp[methodName](args[0])(args[1])(args[2]); });
450 if (typeof result != 'function') {
453 console.log(methodName, result);
457 assert.deepEqual(actual, expected);
461 /*--------------------------------------------------------------------------*/
463 QUnit.module('methods that use `indexOf`');
466 QUnit.test('should work with `fp.indexOf`', function(assert) {
469 var array = ['a', 'b', 'c'],
470 other = ['b', 'd', 'b'],
471 object = { 'a': 1, 'b': 2, 'c': 2 },
472 actual = fp.difference(array)(other);
474 assert.deepEqual(actual, ['a', 'c'], 'fp.difference');
476 actual = fp.includes('b')(array);
477 assert.strictEqual(actual, true, 'fp.includes');
479 actual = fp.intersection(other)(array);
480 assert.deepEqual(actual, ['b'], 'fp.intersection');
482 actual = fp.omit(other)(object);
483 assert.deepEqual(actual, { 'a': 1, 'c': 2 }, 'fp.omit');
485 actual = fp.union(other)(array);
486 assert.deepEqual(actual, ['a', 'b', 'c', 'd'], 'fp.union');
488 actual = fp.uniq(other);
489 assert.deepEqual(actual, ['b', 'd'], 'fp.uniq');
491 actual = fp.uniqBy(_.identity, other);
492 assert.deepEqual(actual, ['b', 'd'], 'fp.uniqBy');
494 actual = fp.without(other)(array);
495 assert.deepEqual(actual, ['a', 'c'], 'fp.without');
497 actual = fp.xor(other)(array);
498 assert.deepEqual(actual, ['a', 'c', 'd'], 'fp.xor');
500 actual = fp.pull('b')(array);
501 assert.deepEqual(actual, ['a', 'c'], 'fp.pull');
505 /*--------------------------------------------------------------------------*/
507 QUnit.module('cherry-picked methods');
510 QUnit.test('should provide the correct `iteratee` arguments', function(assert) {
515 object = { 'a': 1, 'b': 2 },
516 isFIFO = _.keys(object)[0] == 'a',
517 map = convert('map', _.map),
518 reduce = convert('reduce', _.reduce);
521 args || (args = slice.call(arguments));
524 assert.deepEqual(args, [1]);
528 args || (args = slice.call(arguments));
531 assert.deepEqual(args, isFIFO ? [1] : [2]);
535 args || (args = slice.call(arguments));
538 assert.deepEqual(args, [0, 1]);
542 args || (args = slice.call(arguments));
545 assert.deepEqual(args, isFIFO ? [0, 1] : [0, 2]);
548 QUnit.test('should not support shortcut fusion', function(assert) {
551 var array = fp.range(0, LARGE_ARRAY_SIZE),
555 var iteratee = function(value) {
557 return value * value;
560 var predicate = function(value) {
562 return isEven(value);
565 var map1 = convert('map', _.map),
566 filter1 = convert('filter', _.filter),
567 take1 = convert('take', _.take);
569 var filter2 = filter1(predicate),
570 map2 = map1(iteratee),
573 var combined = fp.flow(map2, filter2, fp.compact, take2);
575 assert.deepEqual(combined(array), [4, 16]);
576 assert.strictEqual(filterCount, 200, 'filterCount');
577 assert.strictEqual(mapCount, 200, 'mapCount');
581 /*--------------------------------------------------------------------------*/
583 QUnit.module('iteratee shorthands');
586 var objects = [{ 'a': 1, 'b': 2 }, { 'a': 3, 'b': 4 }];
588 QUnit.test('should work with "_.matches" shorthands', function(assert) {
591 assert.deepEqual(fp.filter({ 'a': 3 })(objects), [objects[1]]);
594 QUnit.test('should work with "_.matchesProperty" shorthands', function(assert) {
597 assert.deepEqual(fp.filter(['a', 3])(objects), [objects[1]]);
600 QUnit.test('should work with "_.property" shorthands', function(assert) {
603 assert.deepEqual(fp.map('a')(objects), [1, 3]);
607 /*--------------------------------------------------------------------------*/
609 QUnit.module('placeholder methods');
612 QUnit.test('should use `fp` as the default placeholder', function(assert) {
615 var actual = fp.add(fp, 'b')('a');
616 assert.strictEqual(actual, 'ab');
618 actual = fp.fill(fp, 2)(1, '*')([1, 2, 3]);
619 assert.deepEqual(actual, [1, '*', 3]);
621 actual = fp.slice(fp, 2)(1)(['a', 'b', 'c']);
622 assert.deepEqual(actual, ['b']);
625 QUnit.test('should support `fp.placeholder`', function(assert) {
628 _.each([[], fp.__], function(ph) {
631 var actual = fp.add(ph, 'b')('a');
632 assert.strictEqual(actual, 'ab');
634 actual = fp.fill(ph, 2)(1, '*')([1, 2, 3]);
635 assert.deepEqual(actual, [1, '*', 3]);
637 actual = fp.slice(ph, 2)(1)(['a', 'b', 'c']);
638 assert.deepEqual(actual, ['b']);
642 _.forOwn(mapping.placeholder, function(truthy, methodName) {
643 var func = fp[methodName];
645 QUnit.test('`_.' + methodName + '` should have a `placeholder` property', function(assert) {
648 assert.ok(_.isObject(func.placeholder));
649 assert.strictEqual(func.placeholder, fp.__);
654 /*--------------------------------------------------------------------------*/
656 QUnit.module('setter methods');
659 QUnit.test('should only clone objects in `path`', function(assert) {
662 var object = { 'a': { 'b': 2, 'c': 3 }, 'd': { 'e': 4 } },
663 value = _.cloneDeep(object),
664 actual = fp.set('a.b.c.d', 5, value);
666 assert.ok(_.isObject(actual.a.b), 'fp.set');
667 assert.ok(_.isNumber(actual.a.b), 'fp.set');
669 assert.strictEqual(actual.a.b.c.d, 5, 'fp.set');
670 assert.strictEqual(actual.d, value.d, 'fp.set');
672 value = _.cloneDeep(object);
673 actual = fp.setWith(Object)('[0][1]')('a')(value);
675 assert.deepEqual(actual[0], { '1': 'a' }, 'fp.setWith');
677 value = _.cloneDeep(object);
678 actual = fp.unset('a.b')(value);
680 assert.notOk('b' in actual.a, 'fp.unset');
681 assert.strictEqual(actual.a.c, value.a.c, 'fp.unset');
683 value = _.cloneDeep(object);
684 actual = fp.update('a.b')(square)(value);
686 assert.strictEqual(actual.a.b, 4, 'fp.update');
687 assert.strictEqual(actual.d, value.d, 'fp.update');
689 value = _.cloneDeep(object);
690 actual = fp.updateWith(Object)('[0][1]')(_.constant('a'))(value);
692 assert.deepEqual(actual[0], { '1': 'a' }, 'fp.updateWith');
693 assert.strictEqual(actual.d, value.d, 'fp.updateWith');
697 /*--------------------------------------------------------------------------*/
699 QUnit.module('fp.add and fp.subtract');
701 _.each(['add', 'subtract'], function(methodName) {
702 var func = fp[methodName],
703 isAdd = methodName == 'add';
705 QUnit.test('`fp.' + methodName + '` should not have `rearg` applied', function(assert) {
708 assert.strictEqual(func('1')('2'), isAdd ? '12' : -1);
712 /*--------------------------------------------------------------------------*/
714 QUnit.module('assign methods');
716 _.each(['assign', 'assignIn', 'defaults', 'defaultsDeep', 'merge'], function(methodName) {
717 var func = fp[methodName];
719 QUnit.test('`fp.' + methodName + '` should not mutate values', function(assert) {
722 var object = { 'a': 1 },
723 actual = func(object)({ 'b': 2 });
725 assert.deepEqual(object, { 'a': 1 });
726 assert.deepEqual(actual, { 'a': 1, 'b': 2 });
730 /*--------------------------------------------------------------------------*/
732 QUnit.module('assignWith methods');
734 _.each(['assignWith', 'assignInWith', 'extendWith'], function(methodName) {
735 var func = fp[methodName];
737 QUnit.test('`fp.' + methodName + '` should provide the correct `customizer` arguments', function(assert) {
743 args || (args = _.map(arguments, _.cloneDeep));
744 })({ 'a': 1 })({ 'b': 2 });
746 assert.deepEqual(args, [undefined, 2, 'b', { 'a': 1 }, { 'b': 2 }]);
749 QUnit.test('`fp.' + methodName + '` should not mutate values', function(assert) {
752 var object = { 'a': 1 };
754 var actual = func(function(objValue, srcValue) {
756 })(object)({ 'b': 2 });
758 assert.deepEqual(object, { 'a': 1 });
759 assert.deepEqual(actual, { 'a': 1, 'b': 2 });
763 /*--------------------------------------------------------------------------*/
765 QUnit.module('fp.castArray');
768 QUnit.test('should shallow clone array values', function(assert) {
772 actual = fp.castArray(array);
774 assert.deepEqual(actual, array);
775 assert.notStrictEqual(actual, array);
778 QUnit.test('should not shallow clone non-array values', function(assert) {
781 var object = { 'a': 1 },
782 actual = fp.castArray(object);
784 assert.deepEqual(actual, [object]);
785 assert.strictEqual(actual[0], object);
788 QUnit.test('should convert by name', function(assert) {
793 castArray = convert('castArray', _.castArray),
794 actual = castArray(array);
796 assert.deepEqual(actual, array);
797 assert.notStrictEqual(actual, array);
799 actual = castArray(object);
800 assert.deepEqual(actual, [object]);
801 assert.strictEqual(actual[0], object);
805 /*--------------------------------------------------------------------------*/
807 QUnit.module('curry methods');
809 _.each(['curry', 'curryRight'], function(methodName) {
810 var func = fp[methodName];
812 QUnit.test('`_.' + methodName + '` should only accept a `func` param', function(assert) {
815 assert.raises(function() { func(1, _.noop); }, TypeError);
819 /*--------------------------------------------------------------------------*/
821 QUnit.module('curryN methods');
823 _.each(['curryN', 'curryRightN'], function(methodName) {
824 var func = fp[methodName];
826 QUnit.test('`_.' + methodName + '` should accept an `arity` param', function(assert) {
829 var actual = func(1)(function(a, b) { return [a, b]; })('a');
830 assert.deepEqual(actual, ['a', undefined]);
834 /*--------------------------------------------------------------------------*/
836 QUnit.module('fp.difference');
839 QUnit.test('should return the elements of the first array not included in the second array', function(assert) {
842 var actual = fp.difference([2, 1], [2, 3]);
843 assert.deepEqual(actual, [1]);
847 /*--------------------------------------------------------------------------*/
849 QUnit.module('fp.differenceBy');
852 QUnit.test('should have an argument order of `iteratee`, `array`, then `values`', function(assert) {
855 var actual = fp.differenceBy(Math.floor, [2.1, 1.2], [2.3, 3.4]);
856 assert.deepEqual(actual, [1.2]);
859 QUnit.test('should provide the correct `iteratee` arguments', function(assert) {
864 fp.differenceBy(function() {
865 args || (args = slice.call(arguments));
866 })([2.1, 1.2], [2.3, 3.4]);
868 assert.deepEqual(args, [2.3]);
872 /*--------------------------------------------------------------------------*/
874 QUnit.module('fp.differenceWith');
877 QUnit.test('should have an argument order of `comparator`, `array`, then `values`', function(assert) {
880 var actual = fp.differenceWith(fp.eq)([2, 1])([2, 3]);
881 assert.deepEqual(actual, [1]);
885 /*--------------------------------------------------------------------------*/
887 QUnit.module('fp.divide and fp.multiply');
889 _.each(['divide', 'multiply'], function(methodName) {
890 var func = fp[methodName],
891 isDivide = methodName == 'divide';
893 QUnit.test('`fp.' + methodName + '` should not have `rearg` applied', function(assert) {
896 assert.strictEqual(func('2')('4'), isDivide ? 0.5 : 8);
900 /*--------------------------------------------------------------------------*/
902 QUnit.module('fp.extend');
905 QUnit.test('should convert by name', function(assert) {
909 Foo.prototype = { 'b': 2 };
911 var object = { 'a': 1 },
912 extend = convert('extend', _.extend),
913 value = _.clone(object),
914 actual = extend(value)(new Foo);
916 assert.deepEqual(value, object);
917 assert.deepEqual(actual, { 'a': 1, 'b': 2 });
921 /*--------------------------------------------------------------------------*/
923 QUnit.module('fp.fill');
926 QUnit.test('should have an argument order of `start`, `end`, then `value`', function(assert) {
929 var array = [1, 2, 3];
930 assert.deepEqual(fp.fill(1)(2)('*')(array), [1, '*', 3]);
933 QUnit.test('should not mutate values', function(assert) {
936 var array = [1, 2, 3],
937 actual = fp.fill(1)(2)('*')(array);
939 assert.deepEqual(array, [1, 2, 3]);
940 assert.deepEqual(actual, [1, '*', 3]);
944 /*--------------------------------------------------------------------------*/
946 QUnit.module('fp.findFrom methods');
948 _.each(['findFrom', 'findIndexFrom', 'findLastFrom', 'findLastIndexFrom'], function(methodName) {
949 var func = fp[methodName];
951 QUnit.test('`_.' + methodName + '` should provide the correct `predicate` arguments', function(assert) {
957 args || (args = slice.call(arguments));
960 assert.deepEqual(args, [2]);
964 /*--------------------------------------------------------------------------*/
966 QUnit.module('fp.findFrom');
969 function resolve(value) {
970 return fp.flow(fp.property('a'), fp.eq(value));
973 QUnit.test('should have an argument order of `value`, `fromIndex`, then `array`', function(assert) {
976 var objects = [{ 'a': 1 }, { 'a': 2 }, { 'a': 1 }, { 'a': 2 }];
978 assert.strictEqual(fp.findFrom(resolve(1))(1)(objects), objects[2]);
979 assert.strictEqual(fp.findFrom(resolve(2))(-2)(objects), objects[3]);
983 /*--------------------------------------------------------------------------*/
985 QUnit.module('fp.findLastFrom');
988 function resolve(value) {
989 return fp.flow(fp.property('a'), fp.eq(value));
992 QUnit.test('should have an argument order of `value`, `fromIndex`, then `array`', function(assert) {
995 var objects = [{ 'a': 1 }, { 'a': 2 }, { 'a': 1 }, { 'a': 2 }];
997 assert.strictEqual(fp.findLastFrom(resolve(1))(1)(objects), objects[0]);
998 assert.strictEqual(fp.findLastFrom(resolve(2))(-2)(objects), objects[1]);
1002 /*--------------------------------------------------------------------------*/
1004 QUnit.module('fp.findIndexFrom and fp.indexOfFrom');
1006 _.each(['findIndexFrom', 'indexOfFrom'], function(methodName) {
1007 var func = fp[methodName],
1008 resolve = methodName == 'findIndexFrom' ? fp.eq : _.identity;
1010 QUnit.test('`_.' + methodName + '` should have an argument order of `value`, `fromIndex`, then `array`', function(assert) {
1013 var array = [1, 2, 3, 1, 2, 3];
1015 assert.deepEqual(func(resolve(1))(2)(array), 3);
1016 assert.deepEqual(func(resolve(2))(-3)(array), 4);
1020 /*--------------------------------------------------------------------------*/
1022 QUnit.module('fp.findLastIndexFrom and fp.lastIndexOfFrom');
1024 _.each(['findLastIndexFrom', 'lastIndexOfFrom'], function(methodName) {
1025 var func = fp[methodName],
1026 resolve = methodName == 'findLastIndexFrom' ? fp.eq : _.identity;
1028 QUnit.test('`_.' + methodName + '` should have an argument order of `value`, `fromIndex`, then `array`', function(assert) {
1031 var array = [1, 2, 3, 1, 2, 3];
1033 assert.deepEqual(func(resolve(2))(3)(array), 1);
1034 assert.deepEqual(func(resolve(3))(-3)(array), 2);
1038 /*--------------------------------------------------------------------------*/
1040 QUnit.module('fp.flatMapDepth');
1043 QUnit.test('should have an argument order of `iteratee`, `depth`, then `collection`', function(assert) {
1046 function duplicate(n) {
1051 object = { 'a': 1, 'b': 2 },
1052 expected = [[1, 1], [2, 2]];
1054 assert.deepEqual(fp.flatMapDepth(duplicate)(2)(array), expected);
1055 assert.deepEqual(fp.flatMapDepth(duplicate)(2)(object), expected);
1059 /*--------------------------------------------------------------------------*/
1061 QUnit.module('flow methods');
1063 _.each(['flow', 'flowRight'], function(methodName) {
1064 var func = fp[methodName],
1065 isFlow = methodName == 'flow';
1067 QUnit.test('`fp.' + methodName + '` should support shortcut fusion', function(assert) {
1072 array = fp.range(0, LARGE_ARRAY_SIZE);
1074 var iteratee = function(value) {
1076 return square(value);
1079 var predicate = function(value) {
1081 return isEven(value);
1084 var filter = fp.filter(predicate),
1085 map = fp.map(iteratee),
1088 _.times(2, function(index) {
1089 var combined = isFlow
1090 ? func(map, filter, fp.compact, take)
1091 : func(take, fp.compact, filter, map);
1093 filterCount = mapCount = 0;
1095 if (WeakMap && WeakMap.name) {
1096 assert.deepEqual(combined(array), [4, 16]);
1097 assert.strictEqual(filterCount, 5, 'filterCount');
1098 assert.strictEqual(mapCount, 5, 'mapCount');
1101 skipAssert(assert, 3);
1107 /*--------------------------------------------------------------------------*/
1109 QUnit.module('forEach methods');
1111 _.each(['forEach', 'forEachRight', 'forIn', 'forInRight', 'forOwn', 'forOwnRight'], function(methodName) {
1112 var func = fp[methodName];
1114 QUnit.test('`fp.' + methodName + '` should provide `value` to `iteratee`', function(assert) {
1120 args || (args = slice.call(arguments));
1123 assert.deepEqual(args, ['a']);
1128 args || (args = slice.call(arguments));
1131 assert.deepEqual(args, [1]);
1135 /*--------------------------------------------------------------------------*/
1137 QUnit.module('fp.getOr');
1140 QUnit.test('should accept a `defaultValue` param', function(assert) {
1143 var actual = fp.getOr('default')('path')({});
1144 assert.strictEqual(actual, 'default');
1148 /*--------------------------------------------------------------------------*/
1150 QUnit.module('fp.gt and fp.gte');
1152 _.each(['gt', 'gte'], function(methodName) {
1153 var func = fp[methodName];
1155 QUnit.test('`fp.' + methodName + '` should have `rearg` applied', function(assert) {
1158 assert.strictEqual(func(2)(1), true);
1162 /*--------------------------------------------------------------------------*/
1164 QUnit.module('fp.inRange');
1167 QUnit.test('should have an argument order of `start`, `end`, then `value`', function(assert) {
1170 assert.strictEqual(fp.inRange(2)(4)(3), true);
1171 assert.strictEqual(fp.inRange(-2)(-6)(-3), true);
1175 /*--------------------------------------------------------------------------*/
1177 QUnit.module('fp.intersectionBy');
1180 QUnit.test('should have an argument order of `iteratee`, `array`, then `values`', function(assert) {
1183 var actual = fp.intersectionBy(Math.floor, [2.1, 1.2], [2.3, 3.4]);
1184 assert.deepEqual(actual, [2.1]);
1187 QUnit.test('should provide the correct `iteratee` arguments', function(assert) {
1192 fp.intersectionBy(function() {
1193 args || (args = slice.call(arguments));
1194 })([2.1, 1.2], [2.3, 3.4]);
1196 assert.deepEqual(args, [2.3]);
1200 /*--------------------------------------------------------------------------*/
1202 QUnit.module('fp.intersectionWith');
1205 QUnit.test('should have an argument order of `comparator`, `array`, then `values`', function(assert) {
1208 var actual = fp.intersectionWith(fp.eq)([2, 1])([2, 3]);
1209 assert.deepEqual(actual, [2]);
1213 /*--------------------------------------------------------------------------*/
1215 QUnit.module('fp.invoke');
1218 QUnit.test('should not accept an `args` param', function(assert) {
1221 var actual = fp.invoke('toUpperCase')('a');
1222 assert.strictEqual(actual, 'A');
1226 /*--------------------------------------------------------------------------*/
1228 QUnit.module('fp.invokeMap');
1231 QUnit.test('should not accept an `args` param', function(assert) {
1234 var actual = fp.invokeMap('toUpperCase')(['a', 'b']);
1235 assert.deepEqual(actual, ['A', 'B']);
1239 /*--------------------------------------------------------------------------*/
1241 QUnit.module('fp.invokeArgs');
1244 QUnit.test('should accept an `args` param', function(assert) {
1247 var actual = fp.invokeArgs('concat')(['b', 'c'])('a');
1248 assert.strictEqual(actual, 'abc');
1252 /*--------------------------------------------------------------------------*/
1254 QUnit.module('fp.invokeArgsMap');
1257 QUnit.test('should accept an `args` param', function(assert) {
1260 var actual = fp.invokeArgsMap('concat')(['b', 'c'])(['a', 'A']);
1261 assert.deepEqual(actual, ['abc', 'Abc']);
1265 /*--------------------------------------------------------------------------*/
1267 QUnit.module('fp.isEqualWith');
1270 QUnit.test('should provide the correct `customizer` arguments', function(assert) {
1275 objects = [{ 'a': 1 }, { 'a': 2 }],
1276 stack = { '__data__': { '__data__': [objects] } },
1277 expected = [1, 2, 'a', objects[0], objects[1], stack];
1279 fp.isEqualWith(function() {
1280 if (++iteration == 2) {
1281 args = _.map(arguments, _.cloneDeep);
1283 })(objects[0])(objects[1]);
1285 args[5] = _.omitBy(args[5], _.isFunction);
1286 args[5].__data__ = _.omitBy(args[5].__data__, _.isFunction);
1288 assert.deepEqual(args, expected);
1292 /*--------------------------------------------------------------------------*/
1294 QUnit.module('fp.isMatchWith');
1297 QUnit.test('should provide the correct `customizer` arguments', function(assert) {
1301 objects = [{ 'a': 1 }, { 'a': 2 }],
1302 stack = { '__data__': { '__data__': [] } },
1303 expected = [2, 1, 'a', objects[1], objects[0], stack];
1305 fp.isMatchWith(function() {
1306 args || (args = _.map(arguments, _.cloneDeep));
1307 })(objects[0])(objects[1]);
1309 args[5] = _.omitBy(args[5], _.isFunction);
1310 args[5].__data__ = _.omitBy(args[5].__data__, _.isFunction);
1312 assert.deepEqual(args, expected);
1316 /*--------------------------------------------------------------------------*/
1318 QUnit.module('fp.iteratee');
1321 QUnit.test('should return a iteratee with capped params', function(assert) {
1324 var func = fp.iteratee(function(a, b, c) { return [a, b, c]; }, 3);
1325 assert.deepEqual(func(1, 2, 3), [1, undefined, undefined]);
1328 QUnit.test('should convert by name', function(assert) {
1331 var iteratee = convert('iteratee', _.iteratee),
1332 func = iteratee(function(a, b, c) { return [a, b, c]; }, 3);
1334 assert.deepEqual(func(1, 2, 3), [1, undefined, undefined]);
1338 /*--------------------------------------------------------------------------*/
1340 QUnit.module('fp.lt and fp.lte');
1342 _.each(['lt', 'lte'], function(methodName) {
1343 var func = fp[methodName];
1345 QUnit.test('`fp.' + methodName + '` should have `rearg` applied', function(assert) {
1348 assert.strictEqual(func(1)(2), true);
1352 /*--------------------------------------------------------------------------*/
1354 QUnit.module('fp.mapKeys');
1357 QUnit.test('should only provide `key` to `iteratee`', function(assert) {
1362 fp.mapKeys(function() {
1363 args || (args = slice.call(arguments));
1366 assert.deepEqual(args, ['a']);
1370 /*--------------------------------------------------------------------------*/
1372 QUnit.module('fp.maxBy and fp.minBy');
1374 _.each(['maxBy', 'minBy'], function(methodName) {
1375 var array = [1, 2, 3],
1376 func = fp[methodName],
1377 isMax = methodName == 'maxBy';
1379 QUnit.test('`fp.' + methodName + '` should work with an `iteratee` argument', function(assert) {
1382 var actual = func(function(num) {
1386 assert.strictEqual(actual, isMax ? 1 : 3);
1389 QUnit.test('`fp.' + methodName + '` should provide the correct `iteratee` arguments', function(assert) {
1395 args || (args = slice.call(arguments));
1398 assert.deepEqual(args, [1]);
1402 /*--------------------------------------------------------------------------*/
1404 QUnit.module('fp.mergeWith');
1407 QUnit.test('should provide the correct `customizer` arguments', function(assert) {
1411 stack = { '__data__': { '__data__': [] } },
1412 expected = [[1], [2, 3], 'a', { 'a': [1] }, { 'a': [2, 3] }, stack];
1414 fp.mergeWith(function() {
1415 args || (args = _.map(arguments, _.cloneDeep));
1416 })({ 'a': [1] })({ 'a': [2, 3] });
1418 args[5] = _.omitBy(args[5], _.isFunction);
1419 args[5].__data__ = _.omitBy(args[5].__data__, _.isFunction);
1421 assert.deepEqual(args, expected);
1424 QUnit.test('should not mutate values', function(assert) {
1427 var object = { 'a': { 'b': 2, 'c': 3 } };
1430 var actual = fp.mergeWith(function(objValue, srcValue) {
1431 if (_.isArray(objValue)) {
1432 return objValue.concat(srcValue);
1434 }, object, { 'a': { 'b': [2, 3] } });
1436 assert.deepEqual(object, { 'a': { 'b': [1], 'c': 3 } });
1437 assert.deepEqual(actual, { 'a': { 'b': [1, 2, 3], 'c': 3 } });
1441 /*--------------------------------------------------------------------------*/
1443 QUnit.module('fp.mixin');
1446 var source = { 'a': _.noop };
1448 QUnit.test('should mixin static methods but not prototype methods', function(assert) {
1453 assert.strictEqual(typeof fp.a, 'function');
1454 assert.notOk('a' in fp.prototype);
1457 delete fp.prototype.a;
1460 QUnit.test('should not assign inherited `source` methods', function(assert) {
1464 Foo.prototype.a = _.noop;
1467 assert.notOk('a' in fp);
1468 assert.notOk('a' in fp.prototype);
1471 delete fp.prototype.a;
1474 QUnit.test('should not remove existing prototype methods', function(assert) {
1477 var each1 = fp.each,
1478 each2 = fp.prototype.each;
1480 fp.mixin({ 'each': source.a });
1482 assert.strictEqual(fp.each, source.a);
1483 assert.strictEqual(fp.prototype.each, each2);
1486 fp.prototype.each = each2;
1489 QUnit.test('should not export to the global when `source` is not an object', function(assert) {
1492 var props = _.without(_.keys(_), '_');
1494 _.times(2, function(index) {
1495 fp.mixin.apply(fp, index ? [1] : []);
1497 assert.ok(_.every(props, function(key) {
1498 return root[key] !== fp[key];
1501 _.each(props, function(key) {
1502 if (root[key] === fp[key]) {
1509 QUnit.test('should convert by name', function(assert) {
1512 var object = { 'mixin': convert('mixin', _.mixin) };
1515 Foo.mixin = object.mixin;
1518 assert.strictEqual(typeof Foo.a, 'function');
1519 assert.notOk('a' in Foo.prototype);
1521 object.mixin(source);
1522 assert.strictEqual(typeof object.a, 'function');
1526 /*--------------------------------------------------------------------------*/
1528 QUnit.module('fp.over');
1531 QUnit.test('should not cap iteratee args', function(assert) {
1534 _.each([fp.over, convert('over', _.over)], function(func) {
1535 var over = func([Math.max, Math.min]);
1536 assert.deepEqual(over(1, 2, 3, 4), [4, 1]);
1541 /*--------------------------------------------------------------------------*/
1543 QUnit.module('fp.omitBy and fp.pickBy');
1545 _.each(['omitBy', 'pickBy'], function(methodName) {
1546 var func = fp[methodName];
1548 QUnit.test('`fp.' + methodName + '` should provide `value` and `key` to `iteratee`', function(assert) {
1554 args || (args = slice.call(arguments));
1557 assert.deepEqual(args, [1, 'a']);
1561 /*--------------------------------------------------------------------------*/
1563 QUnit.module('padChars methods');
1565 _.each(['padChars', 'padCharsStart', 'padCharsEnd'], function(methodName) {
1566 var func = fp[methodName],
1567 isPad = methodName == 'padChars',
1568 isStart = methodName == 'padCharsStart';
1570 QUnit.test('`_.' + methodName + '` should truncate pad characters to fit the pad length', function(assert) {
1574 assert.strictEqual(func('_-')(8)('abc'), '_-abc_-_');
1576 assert.strictEqual(func('_-')(6)('abc'), isStart ? '_-_abc' : 'abc_-_');
1581 /*--------------------------------------------------------------------------*/
1583 QUnit.module('partial methods');
1585 _.each(['partial', 'partialRight'], function(methodName) {
1586 var func = fp[methodName],
1587 isPartial = methodName == 'partial';
1589 QUnit.test('`_.' + methodName + '` should accept an `args` param', function(assert) {
1592 var expected = isPartial ? [1, 2, 3] : [0, 1, 2];
1594 var actual = func(function(a, b, c) {
1596 })([1, 2])(isPartial ? 3 : 0);
1598 assert.deepEqual(actual, expected);
1601 QUnit.test('`_.' + methodName + '` should convert by name', function(assert) {
1604 var expected = isPartial ? [1, 2, 3] : [0, 1, 2],
1605 par = convert(methodName, _[methodName]),
1606 ph = par.placeholder;
1608 var actual = par(function(a, b, c) {
1610 })([1, 2])(isPartial ? 3 : 0);
1612 assert.deepEqual(actual, expected);
1614 actual = par(function(a, b, c) {
1616 })([ph, 2])(isPartial ? 1 : 0, isPartial ? 3 : 1);
1618 assert.deepEqual(actual, expected);
1622 /*--------------------------------------------------------------------------*/
1624 QUnit.module('fp.pull');
1627 QUnit.test('should not mutate values', function(assert) {
1630 var array = [1, 2, 3],
1631 actual = fp.pull(2)(array);
1633 assert.deepEqual(array, [1, 2, 3]);
1634 assert.deepEqual(actual, [1, 3]);
1638 /*--------------------------------------------------------------------------*/
1640 QUnit.module('fp.pullAll');
1643 QUnit.test('should not mutate values', function(assert) {
1646 var array = [1, 2, 3],
1647 actual = fp.pullAll([1, 3])(array);
1649 assert.deepEqual(array, [1, 2, 3]);
1650 assert.deepEqual(actual, [2]);
1654 /*--------------------------------------------------------------------------*/
1656 QUnit.module('fp.pullAt');
1659 QUnit.test('should not mutate values', function(assert) {
1662 var array = [1, 2, 3],
1663 actual = fp.pullAt([0, 2])(array);
1665 assert.deepEqual(array, [1, 2, 3]);
1666 assert.deepEqual(actual, [2]);
1670 /*--------------------------------------------------------------------------*/
1672 QUnit.module('fp.random');
1675 var array = Array(1000);
1677 QUnit.test('should support a `min` and `max` argument', function(assert) {
1683 assert.ok(_.some(array, function() {
1684 var result = fp.random(min)(max);
1685 return result >= min && result <= max;
1690 /*--------------------------------------------------------------------------*/
1692 QUnit.module('fp.range');
1695 QUnit.test('should have an argument order of `start` then `end`', function(assert) {
1698 assert.deepEqual(fp.range(1)(4), [1, 2, 3]);
1702 /*--------------------------------------------------------------------------*/
1704 QUnit.module('reduce methods');
1706 _.each(['reduce', 'reduceRight'], function(methodName) {
1707 var func = fp[methodName],
1708 isReduce = methodName == 'reduce';
1710 QUnit.test('`_.' + methodName + '` should provide the correct `iteratee` arguments when iterating an array', function(assert) {
1716 args || (args = slice.call(arguments));
1719 assert.deepEqual(args, isReduce ? [0, 1] : [0, 3]);
1722 QUnit.test('`_.' + methodName + '` should provide the correct `iteratee` arguments when iterating an object', function(assert) {
1726 object = { 'a': 1, 'b': 2 },
1727 isFIFO = _.keys(object)[0] == 'a';
1729 var expected = isFIFO
1730 ? (isReduce ? [0, 1] : [0, 2])
1731 : (isReduce ? [0, 2] : [0, 1]);
1734 args || (args = slice.call(arguments));
1737 assert.deepEqual(args, expected);
1741 /*--------------------------------------------------------------------------*/
1743 QUnit.module('fp.remove');
1746 QUnit.test('should not mutate values', function(assert) {
1749 var array = [1, 2, 3],
1750 actual = fp.remove(fp.eq(2))(array);
1752 assert.deepEqual(array, [1, 2, 3]);
1753 assert.deepEqual(actual, [1, 3]);
1757 /*--------------------------------------------------------------------------*/
1759 QUnit.module('fp.restFrom');
1762 QUnit.test('should accept a `start` param', function(assert) {
1765 var actual = fp.restFrom(2)(function() {
1766 return slice.call(arguments);
1767 })('a', 'b', 'c', 'd');
1769 assert.deepEqual(actual, ['a', 'b', ['c', 'd']]);
1773 /*--------------------------------------------------------------------------*/
1775 QUnit.module('fp.reverse');
1778 QUnit.test('should not mutate values', function(assert) {
1781 var array = [1, 2, 3],
1782 actual = fp.reverse(array);
1784 assert.deepEqual(array, [1, 2, 3]);
1785 assert.deepEqual(actual, [3, 2, 1]);
1789 /*--------------------------------------------------------------------------*/
1791 QUnit.module('fp.runInContext');
1794 QUnit.test('should return a converted lodash instance', function(assert) {
1797 assert.strictEqual(typeof fp.runInContext({}).curryN, 'function');
1800 QUnit.test('should convert by name', function(assert) {
1803 var runInContext = convert('runInContext', _.runInContext);
1804 assert.strictEqual(typeof runInContext({}).curryN, 'function');
1808 /*--------------------------------------------------------------------------*/
1810 QUnit.module('fp.set');
1813 QUnit.test('should not mutate values', function(assert) {
1816 var object = { 'a': { 'b': 2, 'c': 3 } },
1817 actual = fp.set('a.b')(3)(object);
1819 assert.deepEqual(object, { 'a': { 'b': 2, 'c': 3 } });
1820 assert.deepEqual(actual, { 'a': { 'b': 3, 'c': 3 } });
1824 /*--------------------------------------------------------------------------*/
1826 QUnit.module('fp.setWith');
1829 QUnit.test('should provide the correct `customizer` arguments', function(assert) {
1834 fp.setWith(function() {
1835 args || (args = _.map(arguments, _.cloneDeep));
1836 })('b.c')(2)({ 'a': 1 });
1838 assert.deepEqual(args, [undefined, 'b', { 'a': 1 }]);
1841 QUnit.test('should not mutate values', function(assert) {
1844 var object = { 'a': { 'b': 2, 'c': 3 } },
1845 actual = fp.setWith(Object)('d.e')(4)(object);
1847 assert.deepEqual(object, { 'a': { 'b': 2, 'c': 3 } });
1848 assert.deepEqual(actual, { 'a': { 'b': 2, 'c': 3 }, 'd': { 'e': 4 } });
1852 /*--------------------------------------------------------------------------*/
1854 QUnit.module('fp.spreadFrom');
1857 QUnit.test('should accept a `start` param', function(assert) {
1860 var actual = fp.spreadFrom(2)(function() {
1861 return slice.call(arguments);
1862 })('a', 'b', ['c', 'd']);
1864 assert.deepEqual(actual, ['a', 'b', 'c', 'd']);
1868 /*--------------------------------------------------------------------------*/
1870 QUnit.module('trimChars methods');
1872 _.each(['trimChars', 'trimCharsStart', 'trimCharsEnd'], function(methodName, index) {
1873 var func = fp[methodName],
1877 parts.push('leading');
1880 parts.push('trailing');
1882 parts = parts.join(' and ');
1884 QUnit.test('`_.' + methodName + '` should remove ' + parts + ' `chars`', function(assert) {
1887 var string = '-_-a-b-c-_-',
1888 expected = (index == 2 ? '-_-' : '') + 'a-b-c' + (index == 1 ? '-_-' : '');
1890 assert.strictEqual(func('_-')(string), expected);
1894 /*--------------------------------------------------------------------------*/
1896 QUnit.module('fp.unionBy');
1899 QUnit.test('should have an argument order of `iteratee`, `array`, then `other`', function(assert) {
1902 var actual = fp.unionBy(Math.floor, [2.1], [1.2, 2.3]);
1903 assert.deepEqual(actual, [2.1, 1.2]);
1906 QUnit.test('should provide the correct `iteratee` arguments', function(assert) {
1911 fp.unionBy(function() {
1912 args || (args = slice.call(arguments));
1913 })([2.1], [1.2, 2.3]);
1915 assert.deepEqual(args, [2.1]);
1919 /*--------------------------------------------------------------------------*/
1921 QUnit.module('fp.unionWith');
1924 QUnit.test('should have an argument order of `comparator`, `array`, then `values`', function(assert) {
1927 var actual = fp.unionWith(fp.eq)([2, 1])([2, 3]);
1928 assert.deepEqual(actual, [2, 1, 3]);
1931 QUnit.test('should provide the correct `comparator` arguments', function(assert) {
1936 fp.unionWith(function() {
1937 args || (args = slice.call(arguments));
1940 assert.deepEqual(args, [1, 2]);
1944 /*--------------------------------------------------------------------------*/
1946 QUnit.module('fp.uniqBy');
1949 var objects = [{ 'a': 2 }, { 'a': 3 }, { 'a': 1 }, { 'a': 2 }, { 'a': 3 }, { 'a': 1 }];
1951 QUnit.test('should work with an `iteratee` argument', function(assert) {
1954 var expected = objects.slice(0, 3);
1956 var actual = fp.uniqBy(function(object) {
1960 assert.deepEqual(actual, expected);
1963 QUnit.test('should provide the correct `iteratee` arguments', function(assert) {
1968 fp.uniqBy(function() {
1969 args || (args = slice.call(arguments));
1972 assert.deepEqual(args, [objects[0]]);
1976 /*--------------------------------------------------------------------------*/
1978 QUnit.module('fp.uniqWith');
1981 QUnit.test('should have an argument order of `comparator`, `array`, then `values`', function(assert) {
1984 var actual = fp.uniqWith(fp.eq)([2, 1, 2]);
1985 assert.deepEqual(actual, [2, 1]);
1988 QUnit.test('should provide the correct `comparator` arguments', function(assert) {
1993 fp.uniqWith(function() {
1994 args || (args = slice.call(arguments));
1997 assert.deepEqual(args, [1, 2]);
2001 /*--------------------------------------------------------------------------*/
2003 QUnit.module('fp.update');
2006 QUnit.test('should not convert end of `path` to an object', function(assert) {
2009 var actual = fp.update('a.b')(_.identity)({ 'a': { 'b': 1 } });
2010 assert.strictEqual(typeof actual.a.b, 'number');
2013 QUnit.test('should not mutate values', function(assert) {
2016 var object = { 'a': { 'b': 2, 'c': 3 } },
2017 actual = fp.update('a.b')(square)(object);
2019 assert.deepEqual(object, { 'a': { 'b': 2, 'c': 3 } });
2020 assert.deepEqual(actual, { 'a': { 'b': 4, 'c': 3 } });
2024 /*--------------------------------------------------------------------------*/
2026 QUnit.module('fp.updateWith');
2029 QUnit.test('should provide the correct `customizer` arguments', function(assert) {
2032 fp.updateWith(function() {
2033 args || (args = _.map(arguments, _.cloneDeep));
2034 })('b.c')(_.constant(2))({ 'a': 1 });
2036 assert.deepEqual(args, [undefined, 'b', { 'a': 1 }]);
2039 QUnit.test('should not mutate values', function(assert) {
2042 var object = { 'a': { 'b': 2, 'c': 3 } },
2043 actual = fp.updateWith(Object)('d.e')(_.constant(4))(object);
2045 assert.deepEqual(object, { 'a': { 'b': 2, 'c': 3 } });
2046 assert.deepEqual(actual, { 'a': { 'b': 2, 'c': 3 }, 'd': { 'e': 4 } });
2050 /*--------------------------------------------------------------------------*/
2052 QUnit.module('fp.unset');
2055 QUnit.test('should not mutate values', function(assert) {
2058 var object = { 'a': { 'b': 2, 'c': 3 } },
2059 actual = fp.unset('a.b')(object);
2061 assert.deepEqual(object, { 'a': { 'b': 2, 'c': 3 } });
2062 assert.deepEqual(actual, { 'a': { 'c': 3 } });
2066 /*--------------------------------------------------------------------------*/
2068 QUnit.module('fp.xorBy');
2071 QUnit.test('should have an argument order of `iteratee`, `array`, then `other`', function(assert) {
2074 var actual = fp.xorBy(Math.floor, [2.1, 1.2], [2.3, 3.4]);
2075 assert.deepEqual(actual, [1.2, 3.4]);
2078 QUnit.test('should provide the correct `iteratee` arguments', function(assert) {
2083 fp.xorBy(function() {
2084 args || (args = slice.call(arguments));
2085 })([2.1, 1.2], [2.3, 3.4]);
2087 assert.deepEqual(args, [2.3]);
2091 /*--------------------------------------------------------------------------*/
2093 QUnit.module('fp.xorWith');
2096 QUnit.test('should have an argument order of `comparator`, `array`, then `values`', function(assert) {
2099 var actual = fp.xorWith(fp.eq)([2, 1])([2, 3]);
2100 assert.deepEqual(actual, [1, 3]);
2104 /*--------------------------------------------------------------------------*/
2106 QUnit.module('with methods');
2108 _.each(['differenceWith', 'intersectionWith', 'xorWith'], function(methodName) {
2109 var func = fp[methodName];
2111 QUnit.test('`fp.' + methodName + '` should provide the correct `comparator` arguments', function(assert) {
2117 args || (args = slice.call(arguments));
2120 assert.deepEqual(args, [2, 2]);
2124 /*--------------------------------------------------------------------------*/
2126 QUnit.module('fp.zip');
2129 QUnit.test('should zip together two arrays', function(assert) {
2132 assert.deepEqual(fp.zip([1, 2])([3, 4]), [[1, 3], [2, 4]]);
2136 /*--------------------------------------------------------------------------*/
2138 QUnit.module('fp.zipObject');
2141 QUnit.test('should zip together key/value arrays into an object', function(assert) {
2144 assert.deepEqual(fp.zipObject(['a', 'b'])([1, 2]), { 'a': 1, 'b': 2 });
2148 /*--------------------------------------------------------------------------*/
2150 QUnit.module('fp.zipWith');
2153 QUnit.test('should zip arrays combining grouped elements with `iteratee`', function(assert) {
2156 var array1 = [1, 2, 3],
2158 actual = fp.zipWith(add)(array1)(array2);
2160 assert.deepEqual(actual, [5, 7, 9]);
2164 /*--------------------------------------------------------------------------*/
2166 QUnit.config.asyncRetries = 10;
2167 QUnit.config.hidepassed = true;
2170 QUnit.config.noglobals = true;