Skip to main content
Module

x/lodash/test/test-fp.js

A modern JavaScript utility library delivering modularity, performance, & extras.
Extremely Popular
Latest
File
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323
;(function() { 'use strict';
/** Used as a safe reference for `undefined` in pre-ES5 environments. */ var undefined;
/** Used as the size to cover large array optimizations. */ var LARGE_ARRAY_SIZE = 200;
/** Used as a reference to the global object. */ var root = (typeof global == 'object' && global) || this;
/** Used for native method references. */ var arrayProto = Array.prototype;
/** Method and object shortcuts. */ var phantom = root.phantom, argv = root.process && process.argv, document = !phantom && root.document, slice = arrayProto.slice, WeakMap = root.WeakMap;
/** Math helpers. */ var add = function(x, y) { return x + y; }, isEven = function(n) { return n % 2 == 0; }, isEvenIndex = function(n, index) { return isEven(index); }, square = function(n) { return n * n; };
// Leak to avoid sporadic `noglobals` fails on Edge in Sauce Labs. root.msWDfn = undefined;
/*--------------------------------------------------------------------------*/
/** Load QUnit and extras. */ var QUnit = root.QUnit || require('qunit-extras');
/** Load stable Lodash. */ var _ = root._ || require('../lodash.js');
var convert = (function() { var baseConvert = root.fp || require('../fp/_baseConvert.js'); if (!root.fp) { return function(name, func, options) { return baseConvert(_, name, func, options); }; } return function(name, func, options) { if (typeof name == 'function') { options = func; func = name; name = undefined; } return name === undefined ? baseConvert(func, options) : baseConvert(_.runInContext(), options)[name]; }; }());
var allFalseOptions = { 'cap': false, 'curry': false, 'fixed': false, 'immutable': false, 'rearg': false };
var fp = root.fp ? (fp = _.noConflict(), _ = root._, fp) : convert(_.runInContext());
var mapping = root.mapping || require('../fp/_mapping.js');
/*--------------------------------------------------------------------------*/
/** * Skips a given number of tests with a passing result. * * @private * @param {Object} assert The QUnit assert object. * @param {number} [count=1] The number of tests to skip. */ function skipAssert(assert, count) { count || (count = 1); while (count--) { assert.ok(true, 'test skipped'); } }
/*--------------------------------------------------------------------------*/
if (argv) { console.log('Running lodash/fp tests.'); }
QUnit.module('convert module');
(function() { QUnit.test('should work with `name` and `func`', function(assert) { assert.expect(2);
var array = [1, 2, 3, 4], remove = convert('remove', _.remove), actual = remove(isEven)(array);
assert.deepEqual(array, [1, 2, 3, 4]); assert.deepEqual(actual, [1, 3]); });
QUnit.test('should work with `name`, `func`, and `options`', function(assert) { assert.expect(3);
var array = [1, 2, 3, 4], remove = convert('remove', _.remove, allFalseOptions);
var actual = remove(array, function(n, index) { return isEven(index); });
assert.deepEqual(array, [2, 4]); assert.deepEqual(actual, [1, 3]); assert.deepEqual(remove(), []); });
QUnit.test('should work with an object', function(assert) { assert.expect(2);
if (!document) { var array = [1, 2, 3, 4], lodash = convert({ 'remove': _.remove }), actual = lodash.remove(isEven)(array);
assert.deepEqual(array, [1, 2, 3, 4]); assert.deepEqual(actual, [1, 3]); } else { skipAssert(assert, 2); } });
QUnit.test('should work with an object and `options`', function(assert) { assert.expect(3);
if (!document) { var array = [1, 2, 3, 4], lodash = convert({ 'remove': _.remove }, allFalseOptions), actual = lodash.remove(array, isEvenIndex);
assert.deepEqual(array, [2, 4]); assert.deepEqual(actual, [1, 3]); assert.deepEqual(lodash.remove(), []); } else { skipAssert(assert, 3); } });
QUnit.test('should work with lodash and `options`', function(assert) { assert.expect(3);
var array = [1, 2, 3, 4], lodash = convert(_.runInContext(), allFalseOptions), actual = lodash.remove(array, isEvenIndex);
assert.deepEqual(array, [2, 4]); assert.deepEqual(actual, [1, 3]); assert.deepEqual(lodash.remove(), []); });
QUnit.test('should work with `runInContext` and `options`', function(assert) { assert.expect(3);
var array = [1, 2, 3, 4], runInContext = convert('runInContext', _.runInContext, allFalseOptions), lodash = runInContext(), actual = lodash.remove(array, isEvenIndex);
assert.deepEqual(array, [2, 4]); assert.deepEqual(actual, [1, 3]); assert.deepEqual(lodash.remove(), []); });
QUnit.test('should accept a variety of options', function(assert) { assert.expect(8);
var array = [1, 2, 3, 4], value = _.clone(array), remove = convert('remove', _.remove, { 'cap': false }), actual = remove(isEvenIndex)(value);
assert.deepEqual(value, [1, 2, 3, 4]); assert.deepEqual(actual, [2, 4]);
remove = convert('remove', _.remove, { 'curry': false }); actual = remove(isEven);
assert.deepEqual(actual, []);
var trim = convert('trim', _.trim, { 'fixed': false }); assert.strictEqual(trim('_-abc-_', '_-'), 'abc');
value = _.clone(array); remove = convert('remove', _.remove, { 'immutable': false }); actual = remove(isEven)(value);
assert.deepEqual(value, [1, 3]); assert.deepEqual(actual, [2, 4]);
value = _.clone(array); remove = convert('remove', _.remove, { 'rearg': false }); actual = remove(value)(isEven);
assert.deepEqual(value, [1, 2, 3, 4]); assert.deepEqual(actual, [1, 3]); });
QUnit.test('should respect the `cap` option', function(assert) { assert.expect(1);
var iteratee = convert('iteratee', _.iteratee, { 'cap': false });
var func = iteratee(function(a, b, c) { return [a, b, c]; }, 3);
assert.deepEqual(func(1, 2, 3), [1, 2, 3]); });
QUnit.test('should respect the `rearg` option', function(assert) { assert.expect(1);
var add = convert('add', _.add, { 'rearg': true });
assert.strictEqual(add('2')('1'), '12'); });
QUnit.test('should add a `placeholder` property', function(assert) { assert.expect(2);
if (!document) { var lodash = convert({ 'add': _.add });
assert.strictEqual(lodash.placeholder, lodash); assert.strictEqual(lodash.add.placeholder, lodash); } else { skipAssert(assert, 2); } }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('method.convert');
(function() { QUnit.test('should exist on unconverted methods', function(assert) { assert.expect(2);
var array = [], isArray = fp.isArray.convert({ 'curry': true });
assert.strictEqual(fp.isArray(array), true); assert.strictEqual(isArray()(array), true); });
QUnit.test('should convert method aliases', function(assert) { assert.expect(1);
var all = fp.all.convert({ 'rearg': false }), actual = all([0])(_.identity);
assert.strictEqual(actual, false); });
QUnit.test('should convert remapped methods', function(assert) { assert.expect(1);
var extendAll = fp.extendAll.convert({ 'immutable': false }), object = {};
extendAll([object, { 'a': 1 }, { 'b': 2 }]); assert.deepEqual(object, { 'a': 1, 'b': 2 }); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('convert methods');
_.each(['fp.convert', 'method.convert'], function(methodName) { var isFp = methodName == 'fp.convert', func = isFp ? fp.convert : fp.remove.convert;
QUnit.test('`' + methodName + '` should work with an object', function(assert) { assert.expect(3);
var array = [1, 2, 3, 4], lodash = func(allFalseOptions), remove = isFp ? lodash.remove : lodash, actual = remove(array, isEvenIndex);
assert.deepEqual(array, [2, 4]); assert.deepEqual(actual, [1, 3]); assert.deepEqual(remove(), []); });
QUnit.test('`' + methodName + '` should extend existing configs', function(assert) { assert.expect(2);
var array = [1, 2, 3, 4], lodash = func({ 'cap': false }), remove = (isFp ? lodash.remove : lodash).convert({ 'rearg': false }), actual = remove(array)(isEvenIndex);
assert.deepEqual(array, [1, 2, 3, 4]); assert.deepEqual(actual, [2, 4]); }); });
/*--------------------------------------------------------------------------*/
QUnit.module('method arity checks');
(function() { QUnit.test('should wrap methods with an arity > `1`', function(assert) { assert.expect(1);
var methodNames = _.filter(_.functions(fp), function(methodName) { return fp[methodName].length > 1; });
assert.deepEqual(methodNames, []); });
QUnit.test('should have >= arity of `aryMethod` designation', function(assert) { assert.expect(4);
_.times(4, function(index) { var aryCap = index + 1;
var methodNames = _.filter(mapping.aryMethod[aryCap], function(methodName) { var key = _.get(mapping.remap, methodName, methodName), arity = _[key].length;
return arity != 0 && arity < aryCap; });
assert.deepEqual(methodNames, [], '`aryMethod[' + aryCap + ']`'); }); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('method aliases');
(function() { QUnit.test('should have correct aliases', function(assert) { assert.expect(1);
var actual = _.transform(mapping.aliasToReal, function(result, realName, alias) { result.push([alias, fp[alias] === fp[realName]]); }, []);
assert.deepEqual(_.reject(actual, 1), []); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('method ary caps');
(function() { QUnit.test('should have a cap of 1', function(assert) { assert.expect(1);
var funcMethods = [ 'curry', 'iteratee', 'memoize', 'over', 'overEvery', 'overSome', 'method', 'methodOf', 'rest', 'runInContext' ];
var exceptions = funcMethods.concat('mixin', 'nthArg', 'template'), expected = _.map(mapping.aryMethod[1], _.constant(true));
var actual = _.map(mapping.aryMethod[1], function(methodName) { var arg = _.includes(funcMethods, methodName) ? _.noop : 1, result = _.attempt(function() { return fp[methodName](arg); });
if (_.includes(exceptions, methodName) ? typeof result == 'function' : typeof result != 'function' ) { return true; } console.log(methodName, result); return false; });
assert.deepEqual(actual, expected); });
QUnit.test('should have a cap of 2', function(assert) { assert.expect(1);
var funcMethods = [ 'after', 'ary', 'before', 'bind', 'bindKey', 'curryN', 'debounce', 'delay', 'overArgs', 'partial', 'partialRight', 'rearg', 'throttle', 'wrap' ];
var exceptions = _.without(funcMethods.concat('matchesProperty'), 'delay'), expected = _.map(mapping.aryMethod[2], _.constant(true));
var actual = _.map(mapping.aryMethod[2], function(methodName) { var args = _.includes(funcMethods, methodName) ? [methodName == 'curryN' ? 1 : _.noop, _.noop] : [1, []], result = _.attempt(function() { return fp[methodName](args[0])(args[1]); });
if (_.includes(exceptions, methodName) ? typeof result == 'function' : typeof result != 'function' ) { return true; } console.log(methodName, result); return false; });
assert.deepEqual(actual, expected); });
QUnit.test('should have a cap of 3', function(assert) { assert.expect(1);
var funcMethods = [ 'assignWith', 'extendWith', 'isEqualWith', 'isMatchWith', 'reduce', 'reduceRight', 'transform', 'zipWith' ];
var expected = _.map(mapping.aryMethod[3], _.constant(true));
var actual = _.map(mapping.aryMethod[3], function(methodName) { var args = _.includes(funcMethods, methodName) ? [_.noop, 0, 1] : [0, 1, []], result = _.attempt(function() { return fp[methodName](args[0])(args[1])(args[2]); });
if (typeof result != 'function') { return true; } console.log(methodName, result); return false; });
assert.deepEqual(actual, expected); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('methods that use `indexOf`');
(function() { QUnit.test('should work with `fp.indexOf`', function(assert) { assert.expect(10);
var array = ['a', 'b', 'c'], other = ['b', 'd', 'b'], object = { 'a': 1, 'b': 2, 'c': 2 }, actual = fp.difference(array)(other);
assert.deepEqual(actual, ['a', 'c'], 'fp.difference');
actual = fp.includes('b')(array); assert.strictEqual(actual, true, 'fp.includes');
actual = fp.intersection(other)(array); assert.deepEqual(actual, ['b'], 'fp.intersection');
actual = fp.omit(other)(object); assert.deepEqual(actual, { 'a': 1, 'c': 2 }, 'fp.omit');
actual = fp.union(other)(array); assert.deepEqual(actual, ['a', 'b', 'c', 'd'], 'fp.union');
actual = fp.uniq(other); assert.deepEqual(actual, ['b', 'd'], 'fp.uniq');
actual = fp.uniqBy(_.identity, other); assert.deepEqual(actual, ['b', 'd'], 'fp.uniqBy');
actual = fp.without(other)(array); assert.deepEqual(actual, ['a', 'c'], 'fp.without');
actual = fp.xor(other)(array); assert.deepEqual(actual, ['a', 'c', 'd'], 'fp.xor');
actual = fp.pull('b')(array); assert.deepEqual(actual, ['a', 'c'], 'fp.pull'); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('cherry-picked methods');
(function() { QUnit.test('should provide the correct `iteratee` arguments', function(assert) { assert.expect(4);
var args, array = [1, 2, 3], object = { 'a': 1, 'b': 2 }, isFIFO = _.keys(object)[0] == 'a', map = convert('map', _.map), reduce = convert('reduce', _.reduce);
map(function() { args || (args = slice.call(arguments)); })(array);
assert.deepEqual(args, [1]);
args = undefined; map(function() { args || (args = slice.call(arguments)); })(object);
assert.deepEqual(args, isFIFO ? [1] : [2]);
args = undefined; reduce(function() { args || (args = slice.call(arguments)); })(0)(array);
assert.deepEqual(args, [0, 1]);
args = undefined; reduce(function() { args || (args = slice.call(arguments)); })(0)(object);
assert.deepEqual(args, isFIFO ? [0, 1] : [0, 2]); });
QUnit.test('should not support shortcut fusion', function(assert) { assert.expect(3);
var array = fp.range(0, LARGE_ARRAY_SIZE), filterCount = 0, mapCount = 0;
var iteratee = function(value) { mapCount++; return value * value; };
var predicate = function(value) { filterCount++; return isEven(value); };
var map1 = convert('map', _.map), filter1 = convert('filter', _.filter), take1 = convert('take', _.take);
var filter2 = filter1(predicate), map2 = map1(iteratee), take2 = take1(2);
var combined = fp.flow(map2, filter2, fp.compact, take2);
assert.deepEqual(combined(array), [4, 16]); assert.strictEqual(filterCount, 200, 'filterCount'); assert.strictEqual(mapCount, 200, 'mapCount'); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('iteratee shorthands');
(function() { var objects = [{ 'a': 1, 'b': 2 }, { 'a': 3, 'b': 4 }];
QUnit.test('should work with "_.matches" shorthands', function(assert) { assert.expect(1);
assert.deepEqual(fp.filter({ 'a': 3 })(objects), [objects[1]]); });
QUnit.test('should work with "_.matchesProperty" shorthands', function(assert) { assert.expect(1);
assert.deepEqual(fp.filter(['a', 3])(objects), [objects[1]]); });
QUnit.test('should work with "_.property" shorthands', function(assert) { assert.expect(1);
assert.deepEqual(fp.map('a')(objects), [1, 3]); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('placeholder methods');
(function() { QUnit.test('should use `fp` as the default placeholder', function(assert) { assert.expect(3);
var actual = fp.add(fp, 'b')('a'); assert.strictEqual(actual, 'ab');
actual = fp.fill(fp, 2)(1, '*')([1, 2, 3]); assert.deepEqual(actual, [1, '*', 3]);
actual = fp.slice(fp, 2)(1)(['a', 'b', 'c']); assert.deepEqual(actual, ['b']); });
QUnit.test('should support `fp.placeholder`', function(assert) { assert.expect(6);
_.each([[], fp.__], function(ph) { fp.placeholder = ph;
var actual = fp.add(ph, 'b')('a'); assert.strictEqual(actual, 'ab');
actual = fp.fill(ph, 2)(1, '*')([1, 2, 3]); assert.deepEqual(actual, [1, '*', 3]);
actual = fp.slice(ph, 2)(1)(['a', 'b', 'c']); assert.deepEqual(actual, ['b']); }); });
var methodNames = [ 'bind', 'bindKey', 'curry', 'curryRight', 'partial', 'partialRight' ];
_.each(methodNames, function(methodName) { var func = fp[methodName];
QUnit.test('fp.' + methodName + '` should have a `placeholder` property', function(assert) { assert.expect(2);
assert.ok(_.isObject(func.placeholder)); assert.strictEqual(func.placeholder, fp.__); }); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('setter methods');
(function() { QUnit.test('should only clone objects in `path`', function(assert) { assert.expect(11);
var object = { 'a': { 'b': 2, 'c': 3 }, 'd': { 'e': 4 } }, value = _.cloneDeep(object), actual = fp.set('a.b.c.d', 5, value);
assert.ok(_.isObject(actual.a.b), 'fp.set'); assert.ok(_.isNumber(actual.a.b), 'fp.set');
assert.strictEqual(actual.a.b.c.d, 5, 'fp.set'); assert.strictEqual(actual.d, value.d, 'fp.set');
value = _.cloneDeep(object); actual = fp.setWith(Object)('[0][1]')('a')(value);
assert.deepEqual(actual[0], { '1': 'a' }, 'fp.setWith');
value = _.cloneDeep(object); actual = fp.unset('a.b')(value);
assert.notOk('b' in actual.a, 'fp.unset'); assert.strictEqual(actual.a.c, value.a.c, 'fp.unset');
value = _.cloneDeep(object); actual = fp.update('a.b')(square)(value);
assert.strictEqual(actual.a.b, 4, 'fp.update'); assert.strictEqual(actual.d, value.d, 'fp.update');
value = _.cloneDeep(object); actual = fp.updateWith(Object)('[0][1]')(_.constant('a'))(value);
assert.deepEqual(actual[0], { '1': 'a' }, 'fp.updateWith'); assert.strictEqual(actual.d, value.d, 'fp.updateWith'); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.add and fp.subtract');
_.each(['add', 'subtract'], function(methodName) { var func = fp[methodName], isAdd = methodName == 'add';
QUnit.test('`fp.' + methodName + '` should not have `rearg` applied', function(assert) { assert.expect(1);
assert.strictEqual(func('1')('2'), isAdd ? '12' : -1); }); });
/*--------------------------------------------------------------------------*/
QUnit.module('object assignments');
_.each(['assign', 'assignIn', 'defaults', 'defaultsDeep', 'merge'], function(methodName) { var func = fp[methodName];
QUnit.test('`fp.' + methodName + '` should not mutate values', function(assert) { assert.expect(2);
var object = { 'a': 1 }, actual = func(object)({ 'b': 2 });
assert.deepEqual(object, { 'a': 1 }); assert.deepEqual(actual, { 'a': 1, 'b': 2 }); }); });
_.each(['assignAll', 'assignInAll', 'defaultsAll', 'defaultsDeepAll', 'mergeAll'], function(methodName) { var func = fp[methodName];
QUnit.test('`fp.' + methodName + '` should not mutate values', function(assert) { assert.expect(2);
var objects = [{ 'a': 1 }, { 'b': 2 }], actual = func(objects);
assert.deepEqual(objects[0], { 'a': 1 }); assert.deepEqual(actual, { 'a': 1, 'b': 2 }); }); });
_.each(['assignWith', 'assignInWith', 'extendWith'], function(methodName) { var func = fp[methodName];
QUnit.test('`fp.' + methodName + '` should provide the correct `customizer` arguments', function(assert) { assert.expect(1);
var args;
func(function() { args || (args = _.map(arguments, _.cloneDeep)); })({ 'a': 1 })({ 'b': 2 });
assert.deepEqual(args, [undefined, 2, 'b', { 'a': 1 }, { 'b': 2 }]); }); });
_.each(['assignAllWith', 'assignInAllWith', 'extendAllWith', 'mergeAllWith'], function(methodName) { var func = fp[methodName];
QUnit.test('`fp.' + methodName + '` should not mutate values', function(assert) { assert.expect(2);
var objects = [{ 'a': 1 }, { 'b': 2 }], actual = func(_.noop)(objects);
assert.deepEqual(objects[0], { 'a': 1 }); assert.deepEqual(actual, { 'a': 1, 'b': 2 }); });
QUnit.test('`fp.' + methodName + '` should work with more than two sources', function(assert) { assert.expect(2);
var pass = false, objects = [{ 'a': 1 }, { 'b': 2 }, { 'c': 3 }], actual = func(function() { pass = true; })(objects);
assert.ok(pass); assert.deepEqual(actual, { 'a': 1, 'b': 2, 'c': 3 }); }); });
/*--------------------------------------------------------------------------*/
QUnit.module('fp.castArray');
(function() { QUnit.test('should shallow clone array values', function(assert) { assert.expect(2);
var array = [1], actual = fp.castArray(array);
assert.deepEqual(actual, array); assert.notStrictEqual(actual, array); });
QUnit.test('should not shallow clone non-array values', function(assert) { assert.expect(2);
var object = { 'a': 1 }, actual = fp.castArray(object);
assert.deepEqual(actual, [object]); assert.strictEqual(actual[0], object); });
QUnit.test('should convert by name', function(assert) { assert.expect(4);
var array = [1], object = { 'a': 1 }, castArray = convert('castArray', _.castArray), actual = castArray(array);
assert.deepEqual(actual, array); assert.notStrictEqual(actual, array);
actual = castArray(object); assert.deepEqual(actual, [object]); assert.strictEqual(actual[0], object); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('curry methods');
_.each(['curry', 'curryRight'], function(methodName) { var func = fp[methodName];
QUnit.test('fp.' + methodName + '` should only accept a `func` param', function(assert) { assert.expect(1);
assert.raises(function() { func(1, _.noop); }, TypeError); }); });
/*--------------------------------------------------------------------------*/
QUnit.module('curryN methods');
_.each(['curryN', 'curryRightN'], function(methodName) { var func = fp[methodName];
QUnit.test('fp.' + methodName + '` should accept an `arity` param', function(assert) { assert.expect(1);
var actual = func(1)(function(a, b) { return [a, b]; })('a'); assert.deepEqual(actual, ['a', undefined]); }); });
/*--------------------------------------------------------------------------*/
QUnit.module('fp.defaultTo');
(function() { QUnit.test('should have an argument order of `defaultValue` then `value`', function(assert) { assert.expect(2);
assert.strictEqual(fp.defaultTo(1)(0), 0); assert.strictEqual(fp.defaultTo(1)(undefined), 1); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.difference');
(function() { QUnit.test('should return the elements of the first array not included in the second array', function(assert) { assert.expect(1);
var actual = fp.difference([2, 1], [2, 3]); assert.deepEqual(actual, [1]); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.differenceBy');
(function() { QUnit.test('should have an argument order of `iteratee`, `array`, then `values`', function(assert) { assert.expect(1);
var actual = fp.differenceBy(Math.floor, [2.1, 1.2], [2.3, 3.4]); assert.deepEqual(actual, [1.2]); });
QUnit.test('should provide the correct `iteratee` arguments', function(assert) { assert.expect(1);
var args;
fp.differenceBy(function() { args || (args = slice.call(arguments)); })([2.1, 1.2], [2.3, 3.4]);
assert.deepEqual(args, [2.3]); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.differenceWith');
(function() { QUnit.test('should have an argument order of `comparator`, `array`, then `values`', function(assert) { assert.expect(1);
var actual = fp.differenceWith(fp.eq)([2, 1])([2, 3]); assert.deepEqual(actual, [1]); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.divide and fp.multiply');
_.each(['divide', 'multiply'], function(methodName) { var func = fp[methodName], isDivide = methodName == 'divide';
QUnit.test('`fp.' + methodName + '` should not have `rearg` applied', function(assert) { assert.expect(1);
assert.strictEqual(func('2')('4'), isDivide ? 0.5 : 8); }); });
/*--------------------------------------------------------------------------*/
QUnit.module('fp.extend');
(function() { QUnit.test('should convert by name', function(assert) { assert.expect(2);
function Foo() {} Foo.prototype = { 'b': 2 };
var object = { 'a': 1 }, extend = convert('extend', _.extend), actual = extend(object)(new Foo);
assert.deepEqual(object, { 'a': 1 }); assert.deepEqual(actual, { 'a': 1, 'b': 2 }); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.fill');
(function() { QUnit.test('should have an argument order of `start`, `end`, then `value`', function(assert) { assert.expect(1);
var array = [1, 2, 3]; assert.deepEqual(fp.fill(1)(2)('*')(array), [1, '*', 3]); });
QUnit.test('should not mutate values', function(assert) { assert.expect(2);
var array = [1, 2, 3], actual = fp.fill(1)(2)('*')(array);
assert.deepEqual(array, [1, 2, 3]); assert.deepEqual(actual, [1, '*', 3]); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.findFrom methods');
_.each(['findFrom', 'findIndexFrom', 'findLastFrom', 'findLastIndexFrom'], function(methodName) { var func = fp[methodName];
QUnit.test('fp.' + methodName + '` should provide the correct `predicate` arguments', function(assert) { assert.expect(1);
var args;
func(function() { args || (args = slice.call(arguments)); })(1)([1, 2, 3]);
assert.deepEqual(args, [2]); }); });
/*--------------------------------------------------------------------------*/
QUnit.module('fp.findFrom');
(function() { function resolve(value) { return fp.flow(fp.property('a'), fp.eq(value)); }
QUnit.test('should have an argument order of `value`, `fromIndex`, then `array`', function(assert) { assert.expect(2);
var objects = [{ 'a': 1 }, { 'a': 2 }, { 'a': 1 }, { 'a': 2 }];
assert.strictEqual(fp.findFrom(resolve(1))(1)(objects), objects[2]); assert.strictEqual(fp.findFrom(resolve(2))(-2)(objects), objects[3]); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.findLastFrom');
(function() { function resolve(value) { return fp.flow(fp.property('a'), fp.eq(value)); }
QUnit.test('should have an argument order of `value`, `fromIndex`, then `array`', function(assert) { assert.expect(2);
var objects = [{ 'a': 1 }, { 'a': 2 }, { 'a': 1 }, { 'a': 2 }];
assert.strictEqual(fp.findLastFrom(resolve(1))(1)(objects), objects[0]); assert.strictEqual(fp.findLastFrom(resolve(2))(-2)(objects), objects[1]); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.findIndexFrom and fp.indexOfFrom');
_.each(['findIndexFrom', 'indexOfFrom'], function(methodName) { var func = fp[methodName], resolve = methodName == 'findIndexFrom' ? fp.eq : _.identity;
QUnit.test('fp.' + methodName + '` should have an argument order of `value`, `fromIndex`, then `array`', function(assert) { assert.expect(2);
var array = [1, 2, 3, 1, 2, 3];
assert.strictEqual(func(resolve(1))(2)(array), 3); assert.strictEqual(func(resolve(2))(-3)(array), 4); }); });
/*--------------------------------------------------------------------------*/
QUnit.module('fp.findLastIndexFrom and fp.lastIndexOfFrom');
_.each(['findLastIndexFrom', 'lastIndexOfFrom'], function(methodName) { var func = fp[methodName], resolve = methodName == 'findLastIndexFrom' ? fp.eq : _.identity;
QUnit.test('fp.' + methodName + '` should have an argument order of `value`, `fromIndex`, then `array`', function(assert) { assert.expect(2);
var array = [1, 2, 3, 1, 2, 3];
assert.strictEqual(func(resolve(2))(3)(array), 1); assert.strictEqual(func(resolve(3))(-3)(array), 2); }); });
/*--------------------------------------------------------------------------*/
QUnit.module('fp.flatMapDepth');
(function() { QUnit.test('should have an argument order of `iteratee`, `depth`, then `collection`', function(assert) { assert.expect(2);
function duplicate(n) { return [[[n, n]]]; }
var array = [1, 2], object = { 'a': 1, 'b': 2 }, expected = [[1, 1], [2, 2]];
assert.deepEqual(fp.flatMapDepth(duplicate)(2)(array), expected); assert.deepEqual(fp.flatMapDepth(duplicate)(2)(object), expected); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('flow methods');
_.each(['flow', 'flowRight'], function(methodName) { var func = fp[methodName], isFlow = methodName == 'flow';
QUnit.test('`fp.' + methodName + '` should support shortcut fusion', function(assert) { assert.expect(6);
var filterCount, mapCount, array = fp.range(0, LARGE_ARRAY_SIZE);
var iteratee = function(value) { mapCount++; return square(value); };
var predicate = function(value) { filterCount++; return isEven(value); };
var filter = fp.filter(predicate), map = fp.map(iteratee), take = fp.take(2);
_.times(2, function(index) { var combined = isFlow ? func(map, filter, fp.compact, take) : func(take, fp.compact, filter, map);
filterCount = mapCount = 0;
if (WeakMap && WeakMap.name) { assert.deepEqual(combined(array), [4, 16]); assert.strictEqual(filterCount, 5, 'filterCount'); assert.strictEqual(mapCount, 5, 'mapCount'); } else { skipAssert(assert, 3); } }); }); });
/*--------------------------------------------------------------------------*/
QUnit.module('forEach methods');
_.each(['forEach', 'forEachRight', 'forIn', 'forInRight', 'forOwn', 'forOwnRight'], function(methodName) { var func = fp[methodName];
QUnit.test('`fp.' + methodName + '` should provide `value` to `iteratee`', function(assert) { assert.expect(2);
var args;
func(function() { args || (args = slice.call(arguments)); })(['a']);
assert.deepEqual(args, ['a']);
args = undefined;
func(function() { args || (args = slice.call(arguments)); })({ 'a': 1 });
assert.deepEqual(args, [1]); }); });
/*--------------------------------------------------------------------------*/
QUnit.module('fp.getOr');
(function() { QUnit.test('should accept a `defaultValue` param', function(assert) { assert.expect(1);
var actual = fp.getOr('default')('path')({}); assert.strictEqual(actual, 'default'); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.gt and fp.gte');
_.each(['gt', 'gte'], function(methodName) { var func = fp[methodName];
QUnit.test('`fp.' + methodName + '` should have `rearg` applied', function(assert) { assert.expect(1);
assert.strictEqual(func(2)(1), true); }); });
/*--------------------------------------------------------------------------*/
QUnit.module('fp.inRange');
(function() { QUnit.test('should have an argument order of `start`, `end`, then `value`', function(assert) { assert.expect(2);
assert.strictEqual(fp.inRange(2)(4)(3), true); assert.strictEqual(fp.inRange(-2)(-6)(-3), true); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.intersectionBy');
(function() { QUnit.test('should have an argument order of `iteratee`, `array`, then `values`', function(assert) { assert.expect(1);
var actual = fp.intersectionBy(Math.floor, [2.1, 1.2], [2.3, 3.4]); assert.deepEqual(actual, [2.1]); });
QUnit.test('should provide the correct `iteratee` arguments', function(assert) { assert.expect(1);
var args;
fp.intersectionBy(function() { args || (args = slice.call(arguments)); })([2.1, 1.2], [2.3, 3.4]);
assert.deepEqual(args, [2.3]); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.intersectionWith');
(function() { QUnit.test('should have an argument order of `comparator`, `array`, then `values`', function(assert) { assert.expect(1);
var actual = fp.intersectionWith(fp.eq)([2, 1])([2, 3]); assert.deepEqual(actual, [2]); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.invoke');
(function() { QUnit.test('should not accept an `args` param', function(assert) { assert.expect(1);
var actual = fp.invoke('toUpperCase')('a'); assert.strictEqual(actual, 'A'); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.invokeMap');
(function() { QUnit.test('should not accept an `args` param', function(assert) { assert.expect(1);
var actual = fp.invokeMap('toUpperCase')(['a', 'b']); assert.deepEqual(actual, ['A', 'B']); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.invokeArgs');
(function() { QUnit.test('should accept an `args` param', function(assert) { assert.expect(1);
var actual = fp.invokeArgs('concat')(['b', 'c'])('a'); assert.strictEqual(actual, 'abc'); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.invokeArgsMap');
(function() { QUnit.test('should accept an `args` param', function(assert) { assert.expect(1);
var actual = fp.invokeArgsMap('concat')(['b', 'c'])(['a', 'A']); assert.deepEqual(actual, ['abc', 'Abc']); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.isEqualWith');
(function() { QUnit.test('should provide the correct `customizer` arguments', function(assert) { assert.expect(1);
var args, iteration = 0, objects = [{ 'a': 1 }, { 'a': 2 }], stack = { '__data__': { '__data__': [objects, objects.slice().reverse()], 'size': 2 }, 'size': 2 }, expected = [1, 2, 'a', objects[0], objects[1], stack];
fp.isEqualWith(function() { if (++iteration == 2) { args = _.map(arguments, _.cloneDeep); } })(objects[0])(objects[1]);
args[5] = _.omitBy(args[5], _.isFunction); args[5].__data__ = _.omitBy(args[5].__data__, _.isFunction);
assert.deepEqual(args, expected); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.isMatchWith');
(function() { QUnit.test('should provide the correct `customizer` arguments', function(assert) { assert.expect(1);
var args, objects = [{ 'a': 1 }, { 'a': 2 }], stack = { '__data__': { '__data__': [], 'size': 0 }, 'size': 0 }, expected = [2, 1, 'a', objects[1], objects[0], stack];
fp.isMatchWith(function() { args || (args = _.map(arguments, _.cloneDeep)); })(objects[0])(objects[1]);
args[5] = _.omitBy(args[5], _.isFunction); args[5].__data__ = _.omitBy(args[5].__data__, _.isFunction);
assert.deepEqual(args, expected); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.iteratee');
(function() { QUnit.test('should return a iteratee with capped params', function(assert) { assert.expect(1);
var func = fp.iteratee(function(a, b, c) { return [a, b, c]; }, 3); assert.deepEqual(func(1, 2, 3), [1, undefined, undefined]); });
QUnit.test('should convert by name', function(assert) { assert.expect(1);
var iteratee = convert('iteratee', _.iteratee), func = iteratee(function(a, b, c) { return [a, b, c]; }, 3);
assert.deepEqual(func(1, 2, 3), [1, undefined, undefined]); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.lt and fp.lte');
_.each(['lt', 'lte'], function(methodName) { var func = fp[methodName];
QUnit.test('`fp.' + methodName + '` should have `rearg` applied', function(assert) { assert.expect(1);
assert.strictEqual(func(1)(2), true); }); });
/*--------------------------------------------------------------------------*/
QUnit.module('fp.mapKeys');
(function() { QUnit.test('should only provide `key` to `iteratee`', function(assert) { assert.expect(1);
var args;
fp.mapKeys(function() { args || (args = slice.call(arguments)); }, { 'a': 1 });
assert.deepEqual(args, ['a']); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.maxBy and fp.minBy');
_.each(['maxBy', 'minBy'], function(methodName) { var array = [1, 2, 3], func = fp[methodName], isMax = methodName == 'maxBy';
QUnit.test('`fp.' + methodName + '` should work with an `iteratee` argument', function(assert) { assert.expect(1);
var actual = func(function(num) { return -num; })(array);
assert.strictEqual(actual, isMax ? 1 : 3); });
QUnit.test('`fp.' + methodName + '` should provide the correct `iteratee` arguments', function(assert) { assert.expect(1);
var args;
func(function() { args || (args = slice.call(arguments)); })(array);
assert.deepEqual(args, [1]); }); });
/*--------------------------------------------------------------------------*/
QUnit.module('fp.mergeWith');
(function() { QUnit.test('should provide the correct `customizer` arguments', function(assert) { assert.expect(1);
var args, stack = { '__data__': { '__data__': [], 'size': 0 }, 'size': 0 }, expected = [[1, 2], [3], 'a', { 'a': [1, 2] }, { 'a': [3] }, stack];
fp.mergeWith(function() { args || (args = _.map(arguments, _.cloneDeep)); })({ 'a': [1, 2] })({ 'a': [3] });
args[5] = _.omitBy(args[5], _.isFunction); args[5].__data__ = _.omitBy(args[5].__data__, _.isFunction);
assert.deepEqual(args, expected); });
QUnit.test('should not mutate values', function(assert) { assert.expect(2);
var objects = [{ 'a': [1, 2] }, { 'a': [3] }], actual = fp.mergeWith(_.noop, objects[0], objects[1]);
assert.deepEqual(objects[0], { 'a': [1, 2] }); assert.deepEqual(actual, { 'a': [3, 2] }); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.mergeAllWith');
(function() { QUnit.test('should provide the correct `customizer` arguments', function(assert) { assert.expect(1);
var args, objects = [{ 'a': [1, 2] }, { 'a': [3] }], stack = { '__data__': { '__data__': [], 'size': 0 }, 'size': 0 }, expected = [[1, 2], [3], 'a', { 'a': [1, 2] }, { 'a': [3] }, stack];
fp.mergeAllWith(function() { args || (args = _.map(arguments, _.cloneDeep)); })(objects);
args[5] = _.omitBy(args[5], _.isFunction); args[5].__data__ = _.omitBy(args[5].__data__, _.isFunction);
assert.deepEqual(args, expected); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.mixin');
(function() { var source = { 'a': _.noop };
QUnit.test('should mixin static methods but not prototype methods', function(assert) { assert.expect(2);
fp.mixin(source);
assert.strictEqual(typeof fp.a, 'function'); assert.notOk('a' in fp.prototype);
delete fp.a; delete fp.prototype.a; });
QUnit.test('should not assign inherited `source` methods', function(assert) { assert.expect(2);
function Foo() {} Foo.prototype.a = _.noop; fp.mixin(new Foo);
assert.notOk('a' in fp); assert.notOk('a' in fp.prototype);
delete fp.a; delete fp.prototype.a; });
QUnit.test('should not remove existing prototype methods', function(assert) { assert.expect(2);
var each1 = fp.each, each2 = fp.prototype.each;
fp.mixin({ 'each': source.a });
assert.strictEqual(fp.each, source.a); assert.strictEqual(fp.prototype.each, each2);
fp.each = each1; fp.prototype.each = each2; });
QUnit.test('should not export to the global when `source` is not an object', function(assert) { assert.expect(2);
var props = _.without(_.keys(_), '_');
_.times(2, function(index) { fp.mixin.apply(fp, index ? [1] : []);
assert.ok(_.every(props, function(key) { return root[key] !== fp[key]; }));
_.each(props, function(key) { if (root[key] === fp[key]) { delete root[key]; } }); }); });
QUnit.test('should convert by name', function(assert) { assert.expect(3);
var object = { 'mixin': convert('mixin', _.mixin) };
function Foo() {} Foo.mixin = object.mixin; Foo.mixin(source);
assert.ok('a' in Foo); assert.notOk('a' in Foo.prototype);
object.mixin(source); assert.ok('a' in object); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.nthArg');
(function() { QUnit.test('should return a curried function', function(assert) { assert.expect(2);
var func = fp.nthArg(1); assert.strictEqual(func(1)(2), 2);
func = fp.nthArg(-1); assert.strictEqual(func(1), 1); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.over');
(function() { QUnit.test('should not cap iteratee args', function(assert) { assert.expect(2);
_.each([fp.over, convert('over', _.over)], function(func) { var over = func([Math.max, Math.min]); assert.deepEqual(over(1, 2, 3, 4), [4, 1]); }); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.omitBy and fp.pickBy');
_.each(['omitBy', 'pickBy'], function(methodName) { var func = fp[methodName];
QUnit.test('`fp.' + methodName + '` should provide `value` and `key` to `iteratee`', function(assert) { assert.expect(1);
var args;
func(function() { args || (args = slice.call(arguments)); })({ 'a': 1 });
assert.deepEqual(args, [1, 'a']); }); });
/*--------------------------------------------------------------------------*/
QUnit.module('padChars methods');
_.each(['padChars', 'padCharsStart', 'padCharsEnd'], function(methodName) { var func = fp[methodName], isPad = methodName == 'padChars', isStart = methodName == 'padCharsStart';
QUnit.test('fp.' + methodName + '` should truncate pad characters to fit the pad length', function(assert) { assert.expect(1);
if (isPad) { assert.strictEqual(func('_-')(8)('abc'), '_-abc_-_'); } else { assert.strictEqual(func('_-')(6)('abc'), isStart ? '_-_abc' : 'abc_-_'); } }); });
/*--------------------------------------------------------------------------*/
QUnit.module('partial methods');
_.each(['partial', 'partialRight'], function(methodName) { var func = fp[methodName], isPartial = methodName == 'partial';
QUnit.test('fp.' + methodName + '` should accept an `args` param', function(assert) { assert.expect(1);
var expected = isPartial ? [1, 2, 3] : [0, 1, 2];
var actual = func(function(a, b, c) { return [a, b, c]; })([1, 2])(isPartial ? 3 : 0);
assert.deepEqual(actual, expected); });
QUnit.test('fp.' + methodName + '` should convert by name', function(assert) { assert.expect(2);
var expected = isPartial ? [1, 2, 3] : [0, 1, 2], par = convert(methodName, _[methodName]), ph = par.placeholder;
var actual = par(function(a, b, c) { return [a, b, c]; })([1, 2])(isPartial ? 3 : 0);
assert.deepEqual(actual, expected);
actual = par(function(a, b, c) { return [a, b, c]; })([ph, 2])(isPartial ? 1 : 0, isPartial ? 3 : 1);
assert.deepEqual(actual, expected); }); });
/*--------------------------------------------------------------------------*/
QUnit.module('fp.propertyOf');
(function() { QUnit.test('should be curried', function(assert) { assert.expect(2);
var object = { 'a': 1 };
assert.strictEqual(fp.propertyOf(object, 'a'), 1); assert.strictEqual(fp.propertyOf(object)('a'), 1); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.pull');
(function() { QUnit.test('should not mutate values', function(assert) { assert.expect(2);
var array = [1, 2, 3], actual = fp.pull(2)(array);
assert.deepEqual(array, [1, 2, 3]); assert.deepEqual(actual, [1, 3]); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.pullAll');
(function() { QUnit.test('should not mutate values', function(assert) { assert.expect(2);
var array = [1, 2, 3], actual = fp.pullAll([1, 3])(array);
assert.deepEqual(array, [1, 2, 3]); assert.deepEqual(actual, [2]); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.pullAt');
(function() { QUnit.test('should not mutate values', function(assert) { assert.expect(2);
var array = [1, 2, 3], actual = fp.pullAt([0, 2])(array);
assert.deepEqual(array, [1, 2, 3]); assert.deepEqual(actual, [2]); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.random');
(function() { var array = Array(1000);
QUnit.test('should support a `min` and `max` argument', function(assert) { assert.expect(1);
var min = 5, max = 10;
assert.ok(_.some(array, function() { var result = fp.random(min)(max); return result >= min && result <= max; })); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('range methods');
_.each(['range', 'rangeRight'], function(methodName) { var func = fp[methodName], isRange = methodName == 'range';
QUnit.test('fp.' + methodName + '` should have an argument order of `start` then `end`', function(assert) { assert.expect(1);
assert.deepEqual(func(1)(4), isRange ? [1, 2, 3] : [3, 2, 1]); }); });
/*--------------------------------------------------------------------------*/
QUnit.module('rangeStep methods');
_.each(['rangeStep', 'rangeStepRight'], function(methodName) { var func = fp[methodName], isRange = methodName == 'rangeStep';
QUnit.test('fp.' + methodName + '` should have an argument order of `step`, `start`, then `end`', function(assert) { assert.expect(1);
assert.deepEqual(func(2)(1)(4), isRange ? [1, 3] : [3, 1]); }); });
/*--------------------------------------------------------------------------*/
QUnit.module('fp.rearg');
(function() { function fn(a, b, c) { return [a, b, c]; }
QUnit.test('should be curried', function(assert) { assert.expect(1);
var rearged = fp.rearg([1, 2, 0])(fn); assert.deepEqual(rearged('c', 'a', 'b'), ['a', 'b', 'c']); });
QUnit.test('should return a curried function', function(assert) { assert.expect(1);
var rearged = fp.rearg([1, 2, 0], fn); assert.deepEqual(rearged('c')('a')('b'), ['a', 'b', 'c']); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('reduce methods');
_.each(['reduce', 'reduceRight'], function(methodName) { var func = fp[methodName], isReduce = methodName == 'reduce';
QUnit.test('`fp.' + methodName + '` should provide the correct `iteratee` arguments when iterating an array', function(assert) { assert.expect(1);
var args;
func(function() { args || (args = slice.call(arguments)); })(0)([1, 2, 3]);
assert.deepEqual(args, isReduce ? [0, 1] : [3, 0]); });
QUnit.test('`fp.' + methodName + '` should provide the correct `iteratee` arguments when iterating an object', function(assert) { assert.expect(1);
var args, object = { 'a': 1, 'b': 2 }, isFIFO = _.keys(object)[0] == 'a';
var expected = isFIFO ? (isReduce ? [0, 1] : [2, 0]) : (isReduce ? [0, 2] : [1, 0]);
func(function() { args || (args = slice.call(arguments)); })(0)(object);
assert.deepEqual(args, expected); }); });
/*--------------------------------------------------------------------------*/
QUnit.module('fp.remove');
(function() { QUnit.test('should not mutate values', function(assert) { assert.expect(2);
var array = [1, 2, 3], actual = fp.remove(fp.eq(2))(array);
assert.deepEqual(array, [1, 2, 3]); assert.deepEqual(actual, [1, 3]); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.restFrom');
(function() { QUnit.test('should accept a `start` param', function(assert) { assert.expect(1);
var actual = fp.restFrom(2)(function() { return slice.call(arguments); })('a', 'b', 'c', 'd');
assert.deepEqual(actual, ['a', 'b', ['c', 'd']]); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.reverse');
(function() { QUnit.test('should not mutate values', function(assert) { assert.expect(2);
var array = [1, 2, 3], actual = fp.reverse(array);
assert.deepEqual(array, [1, 2, 3]); assert.deepEqual(actual, [3, 2, 1]); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.runInContext');
(function() { QUnit.test('should return a converted lodash instance', function(assert) { assert.expect(1);
assert.strictEqual(typeof fp.runInContext({}).curryN, 'function'); });
QUnit.test('should convert by name', function(assert) { assert.expect(1);
var runInContext = convert('runInContext', _.runInContext); assert.strictEqual(typeof runInContext({}).curryN, 'function'); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.set');
(function() { QUnit.test('should not mutate values', function(assert) { assert.expect(2);
var object = { 'a': { 'b': 2, 'c': 3 } }, actual = fp.set('a.b')(3)(object);
assert.deepEqual(object, { 'a': { 'b': 2, 'c': 3 } }); assert.deepEqual(actual, { 'a': { 'b': 3, 'c': 3 } }); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.setWith');
(function() { QUnit.test('should provide the correct `customizer` arguments', function(assert) { assert.expect(1);
var args;
fp.setWith(function() { args || (args = _.map(arguments, _.cloneDeep)); })('b.c')(2)({ 'a': 1 });
assert.deepEqual(args, [undefined, 'b', { 'a': 1 }]); });
QUnit.test('should not mutate values', function(assert) { assert.expect(2);
var object = { 'a': { 'b': 2, 'c': 3 } }, actual = fp.setWith(Object)('d.e')(4)(object);
assert.deepEqual(object, { 'a': { 'b': 2, 'c': 3 } }); assert.deepEqual(actual, { 'a': { 'b': 2, 'c': 3 }, 'd': { 'e': 4 } }); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.spreadFrom');
(function() { QUnit.test('should accept a `start` param', function(assert) { assert.expect(1);
var actual = fp.spreadFrom(2)(function() { return slice.call(arguments); })('a', 'b', ['c', 'd']);
assert.deepEqual(actual, ['a', 'b', 'c', 'd']); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('trimChars methods');
_.each(['trimChars', 'trimCharsStart', 'trimCharsEnd'], function(methodName, index) { var func = fp[methodName], parts = [];
if (index != 2) { parts.push('leading'); } if (index != 1) { parts.push('trailing'); } parts = parts.join(' and ');
QUnit.test('`fp.' + methodName + '` should remove ' + parts + ' `chars`', function(assert) { assert.expect(1);
var string = '-_-a-b-c-_-', expected = (index == 2 ? '-_-' : '') + 'a-b-c' + (index == 1 ? '-_-' : '');
assert.strictEqual(func('_-')(string), expected); }); });
/*--------------------------------------------------------------------------*/
QUnit.module('fp.unionBy');
(function() { QUnit.test('should have an argument order of `iteratee`, `array`, then `other`', function(assert) { assert.expect(1);
var actual = fp.unionBy(Math.floor, [2.1], [1.2, 2.3]); assert.deepEqual(actual, [2.1, 1.2]); });
QUnit.test('should provide the correct `iteratee` arguments', function(assert) { assert.expect(1);
var args;
fp.unionBy(function() { args || (args = slice.call(arguments)); })([2.1], [1.2, 2.3]);
assert.deepEqual(args, [2.1]); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.unionWith');
(function() { QUnit.test('should have an argument order of `comparator`, `array`, then `values`', function(assert) { assert.expect(1);
var actual = fp.unionWith(fp.eq)([2, 1])([2, 3]); assert.deepEqual(actual, [2, 1, 3]); });
QUnit.test('should provide the correct `comparator` arguments', function(assert) { assert.expect(1);
var args;
fp.unionWith(function() { args || (args = slice.call(arguments)); })([2, 1])([2, 3]);
assert.deepEqual(args, [1, 2]); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.uniqBy');
(function() { var objects = [{ 'a': 2 }, { 'a': 3 }, { 'a': 1 }, { 'a': 2 }, { 'a': 3 }, { 'a': 1 }];
QUnit.test('should work with an `iteratee` argument', function(assert) { assert.expect(1);
var expected = objects.slice(0, 3), actual = fp.uniqBy(_.property('a'))(objects);
assert.deepEqual(actual, expected); });
QUnit.test('should provide the correct `iteratee` arguments', function(assert) { assert.expect(1);
var args;
fp.uniqBy(function() { args || (args = slice.call(arguments)); })(objects);
assert.deepEqual(args, [objects[0]]); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.uniqWith');
(function() { QUnit.test('should have an argument order of `comparator`, `array`, then `values`', function(assert) { assert.expect(1);
var actual = fp.uniqWith(fp.eq)([2, 1, 2]); assert.deepEqual(actual, [2, 1]); });
QUnit.test('should provide the correct `comparator` arguments', function(assert) { assert.expect(1);
var args;
fp.uniqWith(function() { args || (args = slice.call(arguments)); })([2, 1, 2]);
assert.deepEqual(args, [1, 2]); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.update');
(function() { QUnit.test('should not convert end of `path` to an object', function(assert) { assert.expect(1);
var actual = fp.update('a.b')(_.identity)({ 'a': { 'b': 1 } }); assert.strictEqual(typeof actual.a.b, 'number'); });
QUnit.test('should not convert uncloneables to objects', function(assert) { assert.expect(2);
var object = { 'a': { 'b': _.constant(true) } }, actual = fp.update('a.b')(_.identity)(object);
assert.strictEqual(typeof object.a.b, 'function'); assert.strictEqual(object.a.b, actual.a.b); });
QUnit.test('should not mutate values', function(assert) { assert.expect(2);
var object = { 'a': { 'b': 2, 'c': 3 } }, actual = fp.update('a.b')(square)(object);
assert.deepEqual(object, { 'a': { 'b': 2, 'c': 3 } }); assert.deepEqual(actual, { 'a': { 'b': 4, 'c': 3 } }); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.updateWith');
(function() { QUnit.test('should provide the correct `customizer` arguments', function(assert) { var args;
fp.updateWith(function() { args || (args = _.map(arguments, _.cloneDeep)); })('b.c')(_.constant(2))({ 'a': 1 });
assert.deepEqual(args, [undefined, 'b', { 'a': 1 }]); });
QUnit.test('should not mutate values', function(assert) { assert.expect(2);
var object = { 'a': { 'b': 2, 'c': 3 } }, actual = fp.updateWith(Object)('d.e')(_.constant(4))(object);
assert.deepEqual(object, { 'a': { 'b': 2, 'c': 3 } }); assert.deepEqual(actual, { 'a': { 'b': 2, 'c': 3 }, 'd': { 'e': 4 } }); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.unset');
(function() { QUnit.test('should not mutate values', function(assert) { assert.expect(2);
var object = { 'a': { 'b': 2, 'c': 3 } }, actual = fp.unset('a.b')(object);
assert.deepEqual(object, { 'a': { 'b': 2, 'c': 3 } }); assert.deepEqual(actual, { 'a': { 'c': 3 } }); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.xorBy');
(function() { QUnit.test('should have an argument order of `iteratee`, `array`, then `other`', function(assert) { assert.expect(1);
var actual = fp.xorBy(Math.floor, [2.1, 1.2], [2.3, 3.4]); assert.deepEqual(actual, [1.2, 3.4]); });
QUnit.test('should provide the correct `iteratee` arguments', function(assert) { assert.expect(1);
var args;
fp.xorBy(function() { args || (args = slice.call(arguments)); })([2.1, 1.2], [2.3, 3.4]);
assert.deepEqual(args, [2.3]); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.xorWith');
(function() { QUnit.test('should have an argument order of `comparator`, `array`, then `values`', function(assert) { assert.expect(1);
var actual = fp.xorWith(fp.eq)([2, 1])([2, 3]); assert.deepEqual(actual, [1, 3]); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('with methods');
_.each(['differenceWith', 'intersectionWith', 'xorWith'], function(methodName) { var func = fp[methodName];
QUnit.test('`fp.' + methodName + '` should provide the correct `comparator` arguments', function(assert) { assert.expect(1);
var args;
func(function() { args || (args = slice.call(arguments)); })([2, 1])([2, 3]);
assert.deepEqual(args, [2, 2]); }); });
/*--------------------------------------------------------------------------*/
QUnit.module('fp.zip');
(function() { QUnit.test('should zip together two arrays', function(assert) { assert.expect(1);
assert.deepEqual(fp.zip([1, 2])([3, 4]), [[1, 3], [2, 4]]); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.zipAll');
(function() { QUnit.test('should zip together an array of arrays', function(assert) { assert.expect(1);
assert.deepEqual(fp.zipAll([[1, 2], [3, 4], [5, 6]]), [[1, 3, 5], [2, 4, 6]]); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.zipObject');
(function() { QUnit.test('should zip together key/value arrays into an object', function(assert) { assert.expect(1);
assert.deepEqual(fp.zipObject(['a', 'b'])([1, 2]), { 'a': 1, 'b': 2 }); }); }());
/*--------------------------------------------------------------------------*/
QUnit.module('fp.zipWith');
(function() { QUnit.test('should zip arrays combining grouped elements with `iteratee`', function(assert) { assert.expect(1);
var array1 = [1, 2, 3], array2 = [4, 5, 6], actual = fp.zipWith(add)(array1)(array2);
assert.deepEqual(actual, [5, 7, 9]); }); }());
/*--------------------------------------------------------------------------*/
QUnit.config.asyncRetries = 10; QUnit.config.hidepassed = true;
if (!document) { QUnit.config.noglobals = true; QUnit.load(); QUnit.start(); }}.call(this));