test-fp.js 63 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301
  1. ;(function() {
  2. 'use strict';
  3. /** Used as a safe reference for `undefined` in pre-ES5 environments. */
  4. var undefined;
  5. /** Used as the size to cover large array optimizations. */
  6. var LARGE_ARRAY_SIZE = 200;
  7. /** Used as a reference to the global object. */
  8. var root = (typeof global == 'object' && global) || this;
  9. /** Used for native method references. */
  10. var arrayProto = Array.prototype;
  11. /** Method and object shortcuts. */
  12. var phantom = root.phantom,
  13. argv = root.process && process.argv,
  14. document = !phantom && root.document,
  15. slice = arrayProto.slice,
  16. WeakMap = root.WeakMap;
  17. /** Math helpers. */
  18. var add = function(x, y) { return x + y; },
  19. isEven = function(n) { return n % 2 == 0; },
  20. isEvenIndex = function(n, index) { return isEven(index); },
  21. square = function(n) { return n * n; };
  22. // Leak to avoid sporadic `noglobals` fails on Edge in Sauce Labs.
  23. root.msWDfn = undefined;
  24. /*--------------------------------------------------------------------------*/
  25. /** Load QUnit and extras. */
  26. var QUnit = root.QUnit || require('qunit-extras');
  27. /** Load stable Lodash. */
  28. var _ = root._ || require('../lodash.js');
  29. var convert = (function() {
  30. var baseConvert = root.fp || require('../fp/_baseConvert.js');
  31. if (!root.fp) {
  32. return function(name, func, options) {
  33. return baseConvert(_, name, func, options);
  34. };
  35. }
  36. return function(name, func, options) {
  37. if (typeof name == 'function') {
  38. options = func;
  39. func = name;
  40. name = undefined;
  41. }
  42. return name === undefined
  43. ? baseConvert(func, options)
  44. : baseConvert(_.runInContext(), options)[name];
  45. };
  46. }());
  47. var allFalseOptions = {
  48. 'cap': false,
  49. 'curry': false,
  50. 'fixed': false,
  51. 'immutable': false,
  52. 'rearg': false
  53. };
  54. var fp = root.fp
  55. ? (fp = _.noConflict(), _ = root._, fp)
  56. : convert(_.runInContext());
  57. var mapping = root.mapping || require('../fp/_mapping.js');
  58. /*--------------------------------------------------------------------------*/
  59. /**
  60. * Skips a given number of tests with a passing result.
  61. *
  62. * @private
  63. * @param {Object} assert The QUnit assert object.
  64. * @param {number} [count=1] The number of tests to skip.
  65. */
  66. function skipAssert(assert, count) {
  67. count || (count = 1);
  68. while (count--) {
  69. assert.ok(true, 'test skipped');
  70. }
  71. }
  72. /*--------------------------------------------------------------------------*/
  73. if (argv) {
  74. console.log('Running lodash/fp tests.');
  75. }
  76. QUnit.module('convert module');
  77. (function() {
  78. QUnit.test('should work with `name` and `func`', function(assert) {
  79. assert.expect(2);
  80. var array = [1, 2, 3, 4],
  81. remove = convert('remove', _.remove),
  82. actual = remove(isEven)(array);
  83. assert.deepEqual(array, [1, 2, 3, 4]);
  84. assert.deepEqual(actual, [1, 3]);
  85. });
  86. QUnit.test('should work with `name`, `func`, and `options`', function(assert) {
  87. assert.expect(3);
  88. var array = [1, 2, 3, 4],
  89. remove = convert('remove', _.remove, allFalseOptions);
  90. var actual = remove(array, function(n, index) {
  91. return isEven(index);
  92. });
  93. assert.deepEqual(array, [2, 4]);
  94. assert.deepEqual(actual, [1, 3]);
  95. assert.deepEqual(remove(), []);
  96. });
  97. QUnit.test('should work with an object', function(assert) {
  98. assert.expect(2);
  99. if (!document) {
  100. var array = [1, 2, 3, 4],
  101. lodash = convert({ 'remove': _.remove }),
  102. actual = lodash.remove(isEven)(array);
  103. assert.deepEqual(array, [1, 2, 3, 4]);
  104. assert.deepEqual(actual, [1, 3]);
  105. }
  106. else {
  107. skipAssert(assert, 2);
  108. }
  109. });
  110. QUnit.test('should work with an object and `options`', function(assert) {
  111. assert.expect(3);
  112. if (!document) {
  113. var array = [1, 2, 3, 4],
  114. lodash = convert({ 'remove': _.remove }, allFalseOptions),
  115. actual = lodash.remove(array, isEvenIndex);
  116. assert.deepEqual(array, [2, 4]);
  117. assert.deepEqual(actual, [1, 3]);
  118. assert.deepEqual(lodash.remove(), []);
  119. }
  120. else {
  121. skipAssert(assert, 3);
  122. }
  123. });
  124. QUnit.test('should work with lodash and `options`', function(assert) {
  125. assert.expect(3);
  126. var array = [1, 2, 3, 4],
  127. lodash = convert(_.runInContext(), allFalseOptions),
  128. actual = lodash.remove(array, isEvenIndex);
  129. assert.deepEqual(array, [2, 4]);
  130. assert.deepEqual(actual, [1, 3]);
  131. assert.deepEqual(lodash.remove(), []);
  132. });
  133. QUnit.test('should work with `runInContext` and `options`', function(assert) {
  134. assert.expect(3);
  135. var array = [1, 2, 3, 4],
  136. runInContext = convert('runInContext', _.runInContext, allFalseOptions),
  137. lodash = runInContext(),
  138. actual = lodash.remove(array, isEvenIndex);
  139. assert.deepEqual(array, [2, 4]);
  140. assert.deepEqual(actual, [1, 3]);
  141. assert.deepEqual(lodash.remove(), []);
  142. });
  143. QUnit.test('should accept a variety of options', function(assert) {
  144. assert.expect(8);
  145. var array = [1, 2, 3, 4],
  146. value = _.clone(array),
  147. remove = convert('remove', _.remove, { 'cap': false }),
  148. actual = remove(isEvenIndex)(value);
  149. assert.deepEqual(value, [1, 2, 3, 4]);
  150. assert.deepEqual(actual, [2, 4]);
  151. remove = convert('remove', _.remove, { 'curry': false });
  152. actual = remove(isEven);
  153. assert.deepEqual(actual, []);
  154. var trim = convert('trim', _.trim, { 'fixed': false });
  155. assert.strictEqual(trim('_-abc-_', '_-'), 'abc');
  156. value = _.clone(array);
  157. remove = convert('remove', _.remove, { 'immutable': false });
  158. actual = remove(isEven)(value);
  159. assert.deepEqual(value, [1, 3]);
  160. assert.deepEqual(actual, [2, 4]);
  161. value = _.clone(array);
  162. remove = convert('remove', _.remove, { 'rearg': false });
  163. actual = remove(value)(isEven);
  164. assert.deepEqual(value, [1, 2, 3, 4]);
  165. assert.deepEqual(actual, [1, 3]);
  166. });
  167. QUnit.test('should respect the `cap` option', function(assert) {
  168. assert.expect(1);
  169. var iteratee = convert('iteratee', _.iteratee, { 'cap': false });
  170. var func = iteratee(function(a, b, c) {
  171. return [a, b, c];
  172. }, 3);
  173. assert.deepEqual(func(1, 2, 3), [1, 2, 3]);
  174. });
  175. QUnit.test('should respect the `rearg` option', function(assert) {
  176. assert.expect(1);
  177. var add = convert('add', _.add, { 'rearg': true });
  178. assert.strictEqual(add('2')('1'), '12');
  179. });
  180. QUnit.test('should only add a `placeholder` property if needed', function(assert) {
  181. assert.expect(2);
  182. if (!document) {
  183. var methodNames = _.keys(mapping.placeholder),
  184. expected = _.map(methodNames, _.constant(true));
  185. var actual = _.map(methodNames, function(methodName) {
  186. var object = {};
  187. object[methodName] = _[methodName];
  188. var lodash = convert(object);
  189. return methodName in lodash;
  190. });
  191. assert.deepEqual(actual, expected);
  192. var lodash = convert({ 'add': _.add });
  193. assert.notOk('placeholder' in lodash);
  194. }
  195. else {
  196. skipAssert(assert, 2);
  197. }
  198. });
  199. }());
  200. /*--------------------------------------------------------------------------*/
  201. QUnit.module('method.convert');
  202. (function() {
  203. QUnit.test('should exist on unconverted methods', function(assert) {
  204. assert.expect(2);
  205. var array = [],
  206. isArray = fp.isArray.convert({ 'curry': true });
  207. assert.strictEqual(fp.isArray(array), true);
  208. assert.strictEqual(isArray()(array), true);
  209. });
  210. }());
  211. /*--------------------------------------------------------------------------*/
  212. QUnit.module('convert methods');
  213. _.each(['fp.convert', 'method.convert'], function(methodName) {
  214. var isFp = methodName == 'fp.convert',
  215. func = isFp ? fp.convert : fp.remove.convert;
  216. QUnit.test('`' + methodName + '` should work with an object', function(assert) {
  217. assert.expect(3);
  218. var array = [1, 2, 3, 4],
  219. lodash = func(allFalseOptions),
  220. remove = isFp ? lodash.remove : lodash,
  221. actual = remove(array, isEvenIndex);
  222. assert.deepEqual(array, [2, 4]);
  223. assert.deepEqual(actual, [1, 3]);
  224. assert.deepEqual(remove(), []);
  225. });
  226. QUnit.test('`' + methodName + '` should extend existing configs', function(assert) {
  227. assert.expect(2);
  228. var array = [1, 2, 3, 4],
  229. lodash = func({ 'cap': false }),
  230. remove = (isFp ? lodash.remove : lodash).convert({ 'rearg': false }),
  231. actual = remove(array)(isEvenIndex);
  232. assert.deepEqual(array, [1, 2, 3, 4]);
  233. assert.deepEqual(actual, [2, 4]);
  234. });
  235. });
  236. /*--------------------------------------------------------------------------*/
  237. QUnit.module('method arity checks');
  238. (function() {
  239. QUnit.test('should wrap methods with an arity > `1`', function(assert) {
  240. assert.expect(1);
  241. var methodNames = _.filter(_.functions(fp), function(methodName) {
  242. return fp[methodName].length > 1;
  243. });
  244. assert.deepEqual(methodNames, []);
  245. });
  246. QUnit.test('should have >= arity of `aryMethod` designation', function(assert) {
  247. assert.expect(4);
  248. _.times(4, function(index) {
  249. var aryCap = index + 1;
  250. var methodNames = _.filter(mapping.aryMethod[aryCap], function(methodName) {
  251. var key = _.get(mapping.remap, methodName, methodName),
  252. arity = _[key].length;
  253. return arity != 0 && arity < aryCap;
  254. });
  255. assert.deepEqual(methodNames, [], '`aryMethod[' + aryCap + ']`');
  256. });
  257. });
  258. }());
  259. /*--------------------------------------------------------------------------*/
  260. QUnit.module('method aliases');
  261. (function() {
  262. QUnit.test('should have correct aliases', function(assert) {
  263. assert.expect(1);
  264. var actual = _.transform(mapping.aliasToReal, function(result, realName, alias) {
  265. result.push([alias, fp[alias] === fp[realName]]);
  266. }, []);
  267. assert.deepEqual(_.reject(actual, 1), []);
  268. });
  269. }());
  270. /*--------------------------------------------------------------------------*/
  271. QUnit.module('method ary caps');
  272. (function() {
  273. QUnit.test('should have a cap of 1', function(assert) {
  274. assert.expect(1);
  275. var funcMethods = [
  276. 'curry', 'iteratee', 'memoize', 'over', 'overEvery', 'overSome',
  277. 'method', 'methodOf', 'rest', 'runInContext'
  278. ];
  279. var exceptions = funcMethods.concat('mixin', 'nthArg', 'template'),
  280. expected = _.map(mapping.aryMethod[1], _.constant(true));
  281. var actual = _.map(mapping.aryMethod[1], function(methodName) {
  282. var arg = _.includes(funcMethods, methodName) ? _.noop : 1,
  283. result = _.attempt(function() { return fp[methodName](arg); });
  284. if (_.includes(exceptions, methodName)
  285. ? typeof result == 'function'
  286. : typeof result != 'function'
  287. ) {
  288. return true;
  289. }
  290. console.log(methodName, result);
  291. return false;
  292. });
  293. assert.deepEqual(actual, expected);
  294. });
  295. QUnit.test('should have a cap of 2', function(assert) {
  296. assert.expect(1);
  297. var funcMethods = [
  298. 'after', 'ary', 'before', 'bind', 'bindKey', 'curryN', 'debounce',
  299. 'delay', 'overArgs', 'partial', 'partialRight', 'rearg', 'throttle',
  300. 'wrap'
  301. ];
  302. var exceptions = _.without(funcMethods.concat('matchesProperty'), 'delay'),
  303. expected = _.map(mapping.aryMethod[2], _.constant(true));
  304. var actual = _.map(mapping.aryMethod[2], function(methodName) {
  305. var args = _.includes(funcMethods, methodName) ? [methodName == 'curryN' ? 1 : _.noop, _.noop] : [1, []],
  306. result = _.attempt(function() { return fp[methodName](args[0])(args[1]); });
  307. if (_.includes(exceptions, methodName)
  308. ? typeof result == 'function'
  309. : typeof result != 'function'
  310. ) {
  311. return true;
  312. }
  313. console.log(methodName, result);
  314. return false;
  315. });
  316. assert.deepEqual(actual, expected);
  317. });
  318. QUnit.test('should have a cap of 3', function(assert) {
  319. assert.expect(1);
  320. var funcMethods = [
  321. 'assignWith', 'extendWith', 'isEqualWith', 'isMatchWith', 'reduce',
  322. 'reduceRight', 'transform', 'zipWith'
  323. ];
  324. var expected = _.map(mapping.aryMethod[3], _.constant(true));
  325. var actual = _.map(mapping.aryMethod[3], function(methodName) {
  326. var args = _.includes(funcMethods, methodName) ? [_.noop, 0, 1] : [0, 1, []],
  327. result = _.attempt(function() { return fp[methodName](args[0])(args[1])(args[2]); });
  328. if (typeof result != 'function') {
  329. return true;
  330. }
  331. console.log(methodName, result);
  332. return false;
  333. });
  334. assert.deepEqual(actual, expected);
  335. });
  336. }());
  337. /*--------------------------------------------------------------------------*/
  338. QUnit.module('methods that use `indexOf`');
  339. (function() {
  340. QUnit.test('should work with `fp.indexOf`', function(assert) {
  341. assert.expect(10);
  342. var array = ['a', 'b', 'c'],
  343. other = ['b', 'd', 'b'],
  344. object = { 'a': 1, 'b': 2, 'c': 2 },
  345. actual = fp.difference(array)(other);
  346. assert.deepEqual(actual, ['a', 'c'], 'fp.difference');
  347. actual = fp.includes('b')(array);
  348. assert.strictEqual(actual, true, 'fp.includes');
  349. actual = fp.intersection(other)(array);
  350. assert.deepEqual(actual, ['b'], 'fp.intersection');
  351. actual = fp.omit(other)(object);
  352. assert.deepEqual(actual, { 'a': 1, 'c': 2 }, 'fp.omit');
  353. actual = fp.union(other)(array);
  354. assert.deepEqual(actual, ['a', 'b', 'c', 'd'], 'fp.union');
  355. actual = fp.uniq(other);
  356. assert.deepEqual(actual, ['b', 'd'], 'fp.uniq');
  357. actual = fp.uniqBy(_.identity, other);
  358. assert.deepEqual(actual, ['b', 'd'], 'fp.uniqBy');
  359. actual = fp.without(other)(array);
  360. assert.deepEqual(actual, ['a', 'c'], 'fp.without');
  361. actual = fp.xor(other)(array);
  362. assert.deepEqual(actual, ['a', 'c', 'd'], 'fp.xor');
  363. actual = fp.pull('b')(array);
  364. assert.deepEqual(actual, ['a', 'c'], 'fp.pull');
  365. });
  366. }());
  367. /*--------------------------------------------------------------------------*/
  368. QUnit.module('cherry-picked methods');
  369. (function() {
  370. QUnit.test('should provide the correct `iteratee` arguments', function(assert) {
  371. assert.expect(4);
  372. var args,
  373. array = [1, 2, 3],
  374. object = { 'a': 1, 'b': 2 },
  375. isFIFO = _.keys(object)[0] == 'a',
  376. map = convert('map', _.map),
  377. reduce = convert('reduce', _.reduce);
  378. map(function() {
  379. args || (args = slice.call(arguments));
  380. })(array);
  381. assert.deepEqual(args, [1]);
  382. args = undefined;
  383. map(function() {
  384. args || (args = slice.call(arguments));
  385. })(object);
  386. assert.deepEqual(args, isFIFO ? [1] : [2]);
  387. args = undefined;
  388. reduce(function() {
  389. args || (args = slice.call(arguments));
  390. })(0)(array);
  391. assert.deepEqual(args, [0, 1]);
  392. args = undefined;
  393. reduce(function() {
  394. args || (args = slice.call(arguments));
  395. })(0)(object);
  396. assert.deepEqual(args, isFIFO ? [0, 1] : [0, 2]);
  397. });
  398. QUnit.test('should not support shortcut fusion', function(assert) {
  399. assert.expect(3);
  400. var array = fp.range(0, LARGE_ARRAY_SIZE),
  401. filterCount = 0,
  402. mapCount = 0;
  403. var iteratee = function(value) {
  404. mapCount++;
  405. return value * value;
  406. };
  407. var predicate = function(value) {
  408. filterCount++;
  409. return isEven(value);
  410. };
  411. var map1 = convert('map', _.map),
  412. filter1 = convert('filter', _.filter),
  413. take1 = convert('take', _.take);
  414. var filter2 = filter1(predicate),
  415. map2 = map1(iteratee),
  416. take2 = take1(2);
  417. var combined = fp.flow(map2, filter2, fp.compact, take2);
  418. assert.deepEqual(combined(array), [4, 16]);
  419. assert.strictEqual(filterCount, 200, 'filterCount');
  420. assert.strictEqual(mapCount, 200, 'mapCount');
  421. });
  422. }());
  423. /*--------------------------------------------------------------------------*/
  424. QUnit.module('iteratee shorthands');
  425. (function() {
  426. var objects = [{ 'a': 1, 'b': 2 }, { 'a': 3, 'b': 4 }];
  427. QUnit.test('should work with "_.matches" shorthands', function(assert) {
  428. assert.expect(1);
  429. assert.deepEqual(fp.filter({ 'a': 3 })(objects), [objects[1]]);
  430. });
  431. QUnit.test('should work with "_.matchesProperty" shorthands', function(assert) {
  432. assert.expect(1);
  433. assert.deepEqual(fp.filter(['a', 3])(objects), [objects[1]]);
  434. });
  435. QUnit.test('should work with "_.property" shorthands', function(assert) {
  436. assert.expect(1);
  437. assert.deepEqual(fp.map('a')(objects), [1, 3]);
  438. });
  439. }());
  440. /*--------------------------------------------------------------------------*/
  441. QUnit.module('placeholder methods');
  442. (function() {
  443. QUnit.test('should use `fp` as the default placeholder', function(assert) {
  444. assert.expect(3);
  445. var actual = fp.add(fp, 'b')('a');
  446. assert.strictEqual(actual, 'ab');
  447. actual = fp.fill(fp, 2)(1, '*')([1, 2, 3]);
  448. assert.deepEqual(actual, [1, '*', 3]);
  449. actual = fp.slice(fp, 2)(1)(['a', 'b', 'c']);
  450. assert.deepEqual(actual, ['b']);
  451. });
  452. QUnit.test('should support `fp.placeholder`', function(assert) {
  453. assert.expect(6);
  454. _.each([[], fp.__], function(ph) {
  455. fp.placeholder = ph;
  456. var actual = fp.add(ph, 'b')('a');
  457. assert.strictEqual(actual, 'ab');
  458. actual = fp.fill(ph, 2)(1, '*')([1, 2, 3]);
  459. assert.deepEqual(actual, [1, '*', 3]);
  460. actual = fp.slice(ph, 2)(1)(['a', 'b', 'c']);
  461. assert.deepEqual(actual, ['b']);
  462. });
  463. });
  464. _.forOwn(mapping.placeholder, function(truthy, methodName) {
  465. var func = fp[methodName];
  466. QUnit.test('`_.' + methodName + '` should have a `placeholder` property', function(assert) {
  467. assert.expect(2);
  468. assert.ok(_.isObject(func.placeholder));
  469. assert.strictEqual(func.placeholder, fp.__);
  470. });
  471. });
  472. }());
  473. /*--------------------------------------------------------------------------*/
  474. QUnit.module('setter methods');
  475. (function() {
  476. QUnit.test('should only clone objects in `path`', function(assert) {
  477. assert.expect(11);
  478. var object = { 'a': { 'b': 2, 'c': 3 }, 'd': { 'e': 4 } },
  479. value = _.cloneDeep(object),
  480. actual = fp.set('a.b.c.d', 5, value);
  481. assert.ok(_.isObject(actual.a.b), 'fp.set');
  482. assert.ok(_.isNumber(actual.a.b), 'fp.set');
  483. assert.strictEqual(actual.a.b.c.d, 5, 'fp.set');
  484. assert.strictEqual(actual.d, value.d, 'fp.set');
  485. value = _.cloneDeep(object);
  486. actual = fp.setWith(Object)('[0][1]')('a')(value);
  487. assert.deepEqual(actual[0], { '1': 'a' }, 'fp.setWith');
  488. value = _.cloneDeep(object);
  489. actual = fp.unset('a.b')(value);
  490. assert.notOk('b' in actual.a, 'fp.unset');
  491. assert.strictEqual(actual.a.c, value.a.c, 'fp.unset');
  492. value = _.cloneDeep(object);
  493. actual = fp.update('a.b')(square)(value);
  494. assert.strictEqual(actual.a.b, 4, 'fp.update');
  495. assert.strictEqual(actual.d, value.d, 'fp.update');
  496. value = _.cloneDeep(object);
  497. actual = fp.updateWith(Object)('[0][1]')(_.constant('a'))(value);
  498. assert.deepEqual(actual[0], { '1': 'a' }, 'fp.updateWith');
  499. assert.strictEqual(actual.d, value.d, 'fp.updateWith');
  500. });
  501. }());
  502. /*--------------------------------------------------------------------------*/
  503. QUnit.module('fp.add and fp.subtract');
  504. _.each(['add', 'subtract'], function(methodName) {
  505. var func = fp[methodName],
  506. isAdd = methodName == 'add';
  507. QUnit.test('`fp.' + methodName + '` should not have `rearg` applied', function(assert) {
  508. assert.expect(1);
  509. assert.strictEqual(func('1')('2'), isAdd ? '12' : -1);
  510. });
  511. });
  512. /*--------------------------------------------------------------------------*/
  513. QUnit.module('assign methods');
  514. _.each(['assign', 'assignIn', 'defaults', 'defaultsDeep', 'merge'], function(methodName) {
  515. var func = fp[methodName];
  516. QUnit.test('`fp.' + methodName + '` should not mutate values', function(assert) {
  517. assert.expect(2);
  518. var object = { 'a': 1 },
  519. actual = func(object)({ 'b': 2 });
  520. assert.deepEqual(object, { 'a': 1 });
  521. assert.deepEqual(actual, { 'a': 1, 'b': 2 });
  522. });
  523. });
  524. _.each(['assignAll', 'assignInAll', 'defaultsAll', 'defaultsDeepAll', 'mergeAll'], function(methodName) {
  525. var func = fp[methodName];
  526. QUnit.test('`fp.' + methodName + '` should not mutate values', function(assert) {
  527. assert.expect(2);
  528. var objects = [{ 'a': 1 }, { 'b': 2 }],
  529. actual = func(objects);
  530. assert.deepEqual(objects[0], { 'a': 1 });
  531. assert.deepEqual(actual, { 'a': 1, 'b': 2 });
  532. });
  533. });
  534. /*--------------------------------------------------------------------------*/
  535. QUnit.module('assignWith methods');
  536. _.each(['assignWith', 'assignInWith', 'extendWith'], function(methodName) {
  537. var func = fp[methodName];
  538. QUnit.test('`fp.' + methodName + '` should provide the correct `customizer` arguments', function(assert) {
  539. assert.expect(1);
  540. var args;
  541. func(function() {
  542. args || (args = _.map(arguments, _.cloneDeep));
  543. })({ 'a': 1 })({ 'b': 2 });
  544. assert.deepEqual(args, [undefined, 2, 'b', { 'a': 1 }, { 'b': 2 }]);
  545. });
  546. QUnit.test('`fp.' + methodName + '` should not mutate values', function(assert) {
  547. assert.expect(2);
  548. var objects = [{ 'a': 1 }, { 'b': 2 }],
  549. actual = func(_.nthArg(1))(objects[0])(objects[1]);
  550. assert.deepEqual(objects[0], { 'a': 1 });
  551. assert.deepEqual(actual, { 'a': 1, 'b': 2 });
  552. });
  553. });
  554. _.each(['assignAllWith', 'assignInAllWith', 'extendAllWith'], function(methodName) {
  555. var func = fp[methodName];
  556. QUnit.test('`fp.' + methodName + '` should provide the correct `customizer` arguments', function(assert) {
  557. assert.expect(1);
  558. var args;
  559. func(function() {
  560. args || (args = _.map(arguments, _.cloneDeep));
  561. })([{ 'a': 1 }, { 'b': 2 }]);
  562. assert.deepEqual(args, [undefined, 2, 'b', { 'a': 1 }, { 'b': 2 }]);
  563. });
  564. QUnit.test('`fp.' + methodName + '` should not mutate values', function(assert) {
  565. assert.expect(2);
  566. var objects = [{ 'a': 1 }, { 'b': 2 }],
  567. actual = func(_.nthArg(1))(objects);
  568. assert.deepEqual(objects[0], { 'a': 1 });
  569. assert.deepEqual(actual, { 'a': 1, 'b': 2 });
  570. });
  571. });
  572. /*--------------------------------------------------------------------------*/
  573. QUnit.module('fp.castArray');
  574. (function() {
  575. QUnit.test('should shallow clone array values', function(assert) {
  576. assert.expect(2);
  577. var array = [1],
  578. actual = fp.castArray(array);
  579. assert.deepEqual(actual, array);
  580. assert.notStrictEqual(actual, array);
  581. });
  582. QUnit.test('should not shallow clone non-array values', function(assert) {
  583. assert.expect(2);
  584. var object = { 'a': 1 },
  585. actual = fp.castArray(object);
  586. assert.deepEqual(actual, [object]);
  587. assert.strictEqual(actual[0], object);
  588. });
  589. QUnit.test('should convert by name', function(assert) {
  590. assert.expect(4);
  591. var array = [1],
  592. object = { 'a': 1 },
  593. castArray = convert('castArray', _.castArray),
  594. actual = castArray(array);
  595. assert.deepEqual(actual, array);
  596. assert.notStrictEqual(actual, array);
  597. actual = castArray(object);
  598. assert.deepEqual(actual, [object]);
  599. assert.strictEqual(actual[0], object);
  600. });
  601. }());
  602. /*--------------------------------------------------------------------------*/
  603. QUnit.module('curry methods');
  604. _.each(['curry', 'curryRight'], function(methodName) {
  605. var func = fp[methodName];
  606. QUnit.test('`_.' + methodName + '` should only accept a `func` param', function(assert) {
  607. assert.expect(1);
  608. assert.raises(function() { func(1, _.noop); }, TypeError);
  609. });
  610. });
  611. /*--------------------------------------------------------------------------*/
  612. QUnit.module('curryN methods');
  613. _.each(['curryN', 'curryRightN'], function(methodName) {
  614. var func = fp[methodName];
  615. QUnit.test('`_.' + methodName + '` should accept an `arity` param', function(assert) {
  616. assert.expect(1);
  617. var actual = func(1)(function(a, b) { return [a, b]; })('a');
  618. assert.deepEqual(actual, ['a', undefined]);
  619. });
  620. });
  621. /*--------------------------------------------------------------------------*/
  622. QUnit.module('fp.defaultTo');
  623. (function() {
  624. QUnit.test('should have an argument order of `defaultValue` then `value`', function(assert) {
  625. assert.expect(2);
  626. assert.strictEqual(fp.defaultTo(1)(0), 0);
  627. assert.strictEqual(fp.defaultTo(1)(undefined), 1);
  628. });
  629. }());
  630. /*--------------------------------------------------------------------------*/
  631. QUnit.module('fp.difference');
  632. (function() {
  633. QUnit.test('should return the elements of the first array not included in the second array', function(assert) {
  634. assert.expect(1);
  635. var actual = fp.difference([2, 1], [2, 3]);
  636. assert.deepEqual(actual, [1]);
  637. });
  638. }());
  639. /*--------------------------------------------------------------------------*/
  640. QUnit.module('fp.differenceBy');
  641. (function() {
  642. QUnit.test('should have an argument order of `iteratee`, `array`, then `values`', function(assert) {
  643. assert.expect(1);
  644. var actual = fp.differenceBy(Math.floor, [2.1, 1.2], [2.3, 3.4]);
  645. assert.deepEqual(actual, [1.2]);
  646. });
  647. QUnit.test('should provide the correct `iteratee` arguments', function(assert) {
  648. assert.expect(1);
  649. var args;
  650. fp.differenceBy(function() {
  651. args || (args = slice.call(arguments));
  652. })([2.1, 1.2], [2.3, 3.4]);
  653. assert.deepEqual(args, [2.3]);
  654. });
  655. }());
  656. /*--------------------------------------------------------------------------*/
  657. QUnit.module('fp.differenceWith');
  658. (function() {
  659. QUnit.test('should have an argument order of `comparator`, `array`, then `values`', function(assert) {
  660. assert.expect(1);
  661. var actual = fp.differenceWith(fp.eq)([2, 1])([2, 3]);
  662. assert.deepEqual(actual, [1]);
  663. });
  664. }());
  665. /*--------------------------------------------------------------------------*/
  666. QUnit.module('fp.divide and fp.multiply');
  667. _.each(['divide', 'multiply'], function(methodName) {
  668. var func = fp[methodName],
  669. isDivide = methodName == 'divide';
  670. QUnit.test('`fp.' + methodName + '` should not have `rearg` applied', function(assert) {
  671. assert.expect(1);
  672. assert.strictEqual(func('2')('4'), isDivide ? 0.5 : 8);
  673. });
  674. });
  675. /*--------------------------------------------------------------------------*/
  676. QUnit.module('fp.extend');
  677. (function() {
  678. QUnit.test('should convert by name', function(assert) {
  679. assert.expect(2);
  680. function Foo() {}
  681. Foo.prototype = { 'b': 2 };
  682. var object = { 'a': 1 },
  683. extend = convert('extend', _.extend),
  684. actual = extend(object)(new Foo);
  685. assert.deepEqual(object, { 'a': 1 });
  686. assert.deepEqual(actual, { 'a': 1, 'b': 2 });
  687. });
  688. }());
  689. /*--------------------------------------------------------------------------*/
  690. QUnit.module('fp.fill');
  691. (function() {
  692. QUnit.test('should have an argument order of `start`, `end`, then `value`', function(assert) {
  693. assert.expect(1);
  694. var array = [1, 2, 3];
  695. assert.deepEqual(fp.fill(1)(2)('*')(array), [1, '*', 3]);
  696. });
  697. QUnit.test('should not mutate values', function(assert) {
  698. assert.expect(2);
  699. var array = [1, 2, 3],
  700. actual = fp.fill(1)(2)('*')(array);
  701. assert.deepEqual(array, [1, 2, 3]);
  702. assert.deepEqual(actual, [1, '*', 3]);
  703. });
  704. }());
  705. /*--------------------------------------------------------------------------*/
  706. QUnit.module('fp.findFrom methods');
  707. _.each(['findFrom', 'findIndexFrom', 'findLastFrom', 'findLastIndexFrom'], function(methodName) {
  708. var func = fp[methodName];
  709. QUnit.test('`_.' + methodName + '` should provide the correct `predicate` arguments', function(assert) {
  710. assert.expect(1);
  711. var args;
  712. func(function() {
  713. args || (args = slice.call(arguments));
  714. })(1)([1, 2, 3]);
  715. assert.deepEqual(args, [2]);
  716. });
  717. });
  718. /*--------------------------------------------------------------------------*/
  719. QUnit.module('fp.findFrom');
  720. (function() {
  721. function resolve(value) {
  722. return fp.flow(fp.property('a'), fp.eq(value));
  723. }
  724. QUnit.test('should have an argument order of `value`, `fromIndex`, then `array`', function(assert) {
  725. assert.expect(2);
  726. var objects = [{ 'a': 1 }, { 'a': 2 }, { 'a': 1 }, { 'a': 2 }];
  727. assert.strictEqual(fp.findFrom(resolve(1))(1)(objects), objects[2]);
  728. assert.strictEqual(fp.findFrom(resolve(2))(-2)(objects), objects[3]);
  729. });
  730. }());
  731. /*--------------------------------------------------------------------------*/
  732. QUnit.module('fp.findLastFrom');
  733. (function() {
  734. function resolve(value) {
  735. return fp.flow(fp.property('a'), fp.eq(value));
  736. }
  737. QUnit.test('should have an argument order of `value`, `fromIndex`, then `array`', function(assert) {
  738. assert.expect(2);
  739. var objects = [{ 'a': 1 }, { 'a': 2 }, { 'a': 1 }, { 'a': 2 }];
  740. assert.strictEqual(fp.findLastFrom(resolve(1))(1)(objects), objects[0]);
  741. assert.strictEqual(fp.findLastFrom(resolve(2))(-2)(objects), objects[1]);
  742. });
  743. }());
  744. /*--------------------------------------------------------------------------*/
  745. QUnit.module('fp.findIndexFrom and fp.indexOfFrom');
  746. _.each(['findIndexFrom', 'indexOfFrom'], function(methodName) {
  747. var func = fp[methodName],
  748. resolve = methodName == 'findIndexFrom' ? fp.eq : _.identity;
  749. QUnit.test('`_.' + methodName + '` should have an argument order of `value`, `fromIndex`, then `array`', function(assert) {
  750. assert.expect(2);
  751. var array = [1, 2, 3, 1, 2, 3];
  752. assert.strictEqual(func(resolve(1))(2)(array), 3);
  753. assert.strictEqual(func(resolve(2))(-3)(array), 4);
  754. });
  755. });
  756. /*--------------------------------------------------------------------------*/
  757. QUnit.module('fp.findLastIndexFrom and fp.lastIndexOfFrom');
  758. _.each(['findLastIndexFrom', 'lastIndexOfFrom'], function(methodName) {
  759. var func = fp[methodName],
  760. resolve = methodName == 'findLastIndexFrom' ? fp.eq : _.identity;
  761. QUnit.test('`_.' + methodName + '` should have an argument order of `value`, `fromIndex`, then `array`', function(assert) {
  762. assert.expect(2);
  763. var array = [1, 2, 3, 1, 2, 3];
  764. assert.strictEqual(func(resolve(2))(3)(array), 1);
  765. assert.strictEqual(func(resolve(3))(-3)(array), 2);
  766. });
  767. });
  768. /*--------------------------------------------------------------------------*/
  769. QUnit.module('fp.flatMapDepth');
  770. (function() {
  771. QUnit.test('should have an argument order of `iteratee`, `depth`, then `collection`', function(assert) {
  772. assert.expect(2);
  773. function duplicate(n) {
  774. return [[[n, n]]];
  775. }
  776. var array = [1, 2],
  777. object = { 'a': 1, 'b': 2 },
  778. expected = [[1, 1], [2, 2]];
  779. assert.deepEqual(fp.flatMapDepth(duplicate)(2)(array), expected);
  780. assert.deepEqual(fp.flatMapDepth(duplicate)(2)(object), expected);
  781. });
  782. }());
  783. /*--------------------------------------------------------------------------*/
  784. QUnit.module('flow methods');
  785. _.each(['flow', 'flowRight'], function(methodName) {
  786. var func = fp[methodName],
  787. isFlow = methodName == 'flow';
  788. QUnit.test('`fp.' + methodName + '` should support shortcut fusion', function(assert) {
  789. assert.expect(6);
  790. var filterCount,
  791. mapCount,
  792. array = fp.range(0, LARGE_ARRAY_SIZE);
  793. var iteratee = function(value) {
  794. mapCount++;
  795. return square(value);
  796. };
  797. var predicate = function(value) {
  798. filterCount++;
  799. return isEven(value);
  800. };
  801. var filter = fp.filter(predicate),
  802. map = fp.map(iteratee),
  803. take = fp.take(2);
  804. _.times(2, function(index) {
  805. var combined = isFlow
  806. ? func(map, filter, fp.compact, take)
  807. : func(take, fp.compact, filter, map);
  808. filterCount = mapCount = 0;
  809. if (WeakMap && WeakMap.name) {
  810. assert.deepEqual(combined(array), [4, 16]);
  811. assert.strictEqual(filterCount, 5, 'filterCount');
  812. assert.strictEqual(mapCount, 5, 'mapCount');
  813. }
  814. else {
  815. skipAssert(assert, 3);
  816. }
  817. });
  818. });
  819. });
  820. /*--------------------------------------------------------------------------*/
  821. QUnit.module('forEach methods');
  822. _.each(['forEach', 'forEachRight', 'forIn', 'forInRight', 'forOwn', 'forOwnRight'], function(methodName) {
  823. var func = fp[methodName];
  824. QUnit.test('`fp.' + methodName + '` should provide `value` to `iteratee`', function(assert) {
  825. assert.expect(2);
  826. var args;
  827. func(function() {
  828. args || (args = slice.call(arguments));
  829. })(['a']);
  830. assert.deepEqual(args, ['a']);
  831. args = undefined;
  832. func(function() {
  833. args || (args = slice.call(arguments));
  834. })({ 'a': 1 });
  835. assert.deepEqual(args, [1]);
  836. });
  837. });
  838. /*--------------------------------------------------------------------------*/
  839. QUnit.module('fp.getOr');
  840. (function() {
  841. QUnit.test('should accept a `defaultValue` param', function(assert) {
  842. assert.expect(1);
  843. var actual = fp.getOr('default')('path')({});
  844. assert.strictEqual(actual, 'default');
  845. });
  846. }());
  847. /*--------------------------------------------------------------------------*/
  848. QUnit.module('fp.gt and fp.gte');
  849. _.each(['gt', 'gte'], function(methodName) {
  850. var func = fp[methodName];
  851. QUnit.test('`fp.' + methodName + '` should have `rearg` applied', function(assert) {
  852. assert.expect(1);
  853. assert.strictEqual(func(2)(1), true);
  854. });
  855. });
  856. /*--------------------------------------------------------------------------*/
  857. QUnit.module('fp.inRange');
  858. (function() {
  859. QUnit.test('should have an argument order of `start`, `end`, then `value`', function(assert) {
  860. assert.expect(2);
  861. assert.strictEqual(fp.inRange(2)(4)(3), true);
  862. assert.strictEqual(fp.inRange(-2)(-6)(-3), true);
  863. });
  864. }());
  865. /*--------------------------------------------------------------------------*/
  866. QUnit.module('fp.intersectionBy');
  867. (function() {
  868. QUnit.test('should have an argument order of `iteratee`, `array`, then `values`', function(assert) {
  869. assert.expect(1);
  870. var actual = fp.intersectionBy(Math.floor, [2.1, 1.2], [2.3, 3.4]);
  871. assert.deepEqual(actual, [2.1]);
  872. });
  873. QUnit.test('should provide the correct `iteratee` arguments', function(assert) {
  874. assert.expect(1);
  875. var args;
  876. fp.intersectionBy(function() {
  877. args || (args = slice.call(arguments));
  878. })([2.1, 1.2], [2.3, 3.4]);
  879. assert.deepEqual(args, [2.3]);
  880. });
  881. }());
  882. /*--------------------------------------------------------------------------*/
  883. QUnit.module('fp.intersectionWith');
  884. (function() {
  885. QUnit.test('should have an argument order of `comparator`, `array`, then `values`', function(assert) {
  886. assert.expect(1);
  887. var actual = fp.intersectionWith(fp.eq)([2, 1])([2, 3]);
  888. assert.deepEqual(actual, [2]);
  889. });
  890. }());
  891. /*--------------------------------------------------------------------------*/
  892. QUnit.module('fp.invoke');
  893. (function() {
  894. QUnit.test('should not accept an `args` param', function(assert) {
  895. assert.expect(1);
  896. var actual = fp.invoke('toUpperCase')('a');
  897. assert.strictEqual(actual, 'A');
  898. });
  899. }());
  900. /*--------------------------------------------------------------------------*/
  901. QUnit.module('fp.invokeMap');
  902. (function() {
  903. QUnit.test('should not accept an `args` param', function(assert) {
  904. assert.expect(1);
  905. var actual = fp.invokeMap('toUpperCase')(['a', 'b']);
  906. assert.deepEqual(actual, ['A', 'B']);
  907. });
  908. }());
  909. /*--------------------------------------------------------------------------*/
  910. QUnit.module('fp.invokeArgs');
  911. (function() {
  912. QUnit.test('should accept an `args` param', function(assert) {
  913. assert.expect(1);
  914. var actual = fp.invokeArgs('concat')(['b', 'c'])('a');
  915. assert.strictEqual(actual, 'abc');
  916. });
  917. }());
  918. /*--------------------------------------------------------------------------*/
  919. QUnit.module('fp.invokeArgsMap');
  920. (function() {
  921. QUnit.test('should accept an `args` param', function(assert) {
  922. assert.expect(1);
  923. var actual = fp.invokeArgsMap('concat')(['b', 'c'])(['a', 'A']);
  924. assert.deepEqual(actual, ['abc', 'Abc']);
  925. });
  926. }());
  927. /*--------------------------------------------------------------------------*/
  928. QUnit.module('fp.isEqualWith');
  929. (function() {
  930. QUnit.test('should provide the correct `customizer` arguments', function(assert) {
  931. assert.expect(1);
  932. var args,
  933. iteration = 0,
  934. objects = [{ 'a': 1 }, { 'a': 2 }],
  935. stack = { '__data__': { '__data__': [objects, objects.slice().reverse()] } },
  936. expected = [1, 2, 'a', objects[0], objects[1], stack];
  937. fp.isEqualWith(function() {
  938. if (++iteration == 2) {
  939. args = _.map(arguments, _.cloneDeep);
  940. }
  941. })(objects[0])(objects[1]);
  942. args[5] = _.omitBy(args[5], _.isFunction);
  943. args[5].__data__ = _.omitBy(args[5].__data__, _.isFunction);
  944. assert.deepEqual(args, expected);
  945. });
  946. }());
  947. /*--------------------------------------------------------------------------*/
  948. QUnit.module('fp.isMatchWith');
  949. (function() {
  950. QUnit.test('should provide the correct `customizer` arguments', function(assert) {
  951. assert.expect(1);
  952. var args,
  953. objects = [{ 'a': 1 }, { 'a': 2 }],
  954. stack = { '__data__': { '__data__': [] } },
  955. expected = [2, 1, 'a', objects[1], objects[0], stack];
  956. fp.isMatchWith(function() {
  957. args || (args = _.map(arguments, _.cloneDeep));
  958. })(objects[0])(objects[1]);
  959. args[5] = _.omitBy(args[5], _.isFunction);
  960. args[5].__data__ = _.omitBy(args[5].__data__, _.isFunction);
  961. assert.deepEqual(args, expected);
  962. });
  963. }());
  964. /*--------------------------------------------------------------------------*/
  965. QUnit.module('fp.iteratee');
  966. (function() {
  967. QUnit.test('should return a iteratee with capped params', function(assert) {
  968. assert.expect(1);
  969. var func = fp.iteratee(function(a, b, c) { return [a, b, c]; }, 3);
  970. assert.deepEqual(func(1, 2, 3), [1, undefined, undefined]);
  971. });
  972. QUnit.test('should convert by name', function(assert) {
  973. assert.expect(1);
  974. var iteratee = convert('iteratee', _.iteratee),
  975. func = iteratee(function(a, b, c) { return [a, b, c]; }, 3);
  976. assert.deepEqual(func(1, 2, 3), [1, undefined, undefined]);
  977. });
  978. }());
  979. /*--------------------------------------------------------------------------*/
  980. QUnit.module('fp.lt and fp.lte');
  981. _.each(['lt', 'lte'], function(methodName) {
  982. var func = fp[methodName];
  983. QUnit.test('`fp.' + methodName + '` should have `rearg` applied', function(assert) {
  984. assert.expect(1);
  985. assert.strictEqual(func(1)(2), true);
  986. });
  987. });
  988. /*--------------------------------------------------------------------------*/
  989. QUnit.module('fp.mapKeys');
  990. (function() {
  991. QUnit.test('should only provide `key` to `iteratee`', function(assert) {
  992. assert.expect(1);
  993. var args;
  994. fp.mapKeys(function() {
  995. args || (args = slice.call(arguments));
  996. }, { 'a': 1 });
  997. assert.deepEqual(args, ['a']);
  998. });
  999. }());
  1000. /*--------------------------------------------------------------------------*/
  1001. QUnit.module('fp.maxBy and fp.minBy');
  1002. _.each(['maxBy', 'minBy'], function(methodName) {
  1003. var array = [1, 2, 3],
  1004. func = fp[methodName],
  1005. isMax = methodName == 'maxBy';
  1006. QUnit.test('`fp.' + methodName + '` should work with an `iteratee` argument', function(assert) {
  1007. assert.expect(1);
  1008. var actual = func(function(num) {
  1009. return -num;
  1010. })(array);
  1011. assert.strictEqual(actual, isMax ? 1 : 3);
  1012. });
  1013. QUnit.test('`fp.' + methodName + '` should provide the correct `iteratee` arguments', function(assert) {
  1014. assert.expect(1);
  1015. var args;
  1016. func(function() {
  1017. args || (args = slice.call(arguments));
  1018. })(array);
  1019. assert.deepEqual(args, [1]);
  1020. });
  1021. });
  1022. /*--------------------------------------------------------------------------*/
  1023. QUnit.module('fp.mergeWith');
  1024. (function() {
  1025. QUnit.test('should provide the correct `customizer` arguments', function(assert) {
  1026. assert.expect(1);
  1027. var args,
  1028. stack = { '__data__': { '__data__': [] } },
  1029. expected = [[1, 2], [3], 'a', { 'a': [1, 2] }, { 'a': [3] }, stack];
  1030. fp.mergeWith(function() {
  1031. args || (args = _.map(arguments, _.cloneDeep));
  1032. })({ 'a': [1, 2] })({ 'a': [3] });
  1033. args[5] = _.omitBy(args[5], _.isFunction);
  1034. args[5].__data__ = _.omitBy(args[5].__data__, _.isFunction);
  1035. assert.deepEqual(args, expected);
  1036. });
  1037. QUnit.test('should not mutate values', function(assert) {
  1038. assert.expect(2);
  1039. var objects = [{ 'a': [1, 2] }, { 'a': [3] }],
  1040. actual = fp.mergeWith(_.noop, objects[0], objects[1]);
  1041. assert.deepEqual(objects[0], { 'a': [1, 2] });
  1042. assert.deepEqual(actual, { 'a': [3, 2] });
  1043. });
  1044. }());
  1045. /*--------------------------------------------------------------------------*/
  1046. QUnit.module('fp.mergeAllWith');
  1047. (function() {
  1048. QUnit.test('should provide the correct `customizer` arguments', function(assert) {
  1049. assert.expect(1);
  1050. var args,
  1051. stack = { '__data__': { '__data__': [] } },
  1052. expected = [[1, 2], [3], 'a', { 'a': [1, 2] }, { 'a': [3] }, stack];
  1053. fp.mergeAllWith(function() {
  1054. args || (args = _.map(arguments, _.cloneDeep));
  1055. })([{ 'a': [1, 2] }, { 'a': [3] }]);
  1056. args[5] = _.omitBy(args[5], _.isFunction);
  1057. args[5].__data__ = _.omitBy(args[5].__data__, _.isFunction);
  1058. assert.deepEqual(args, expected);
  1059. });
  1060. QUnit.test('should not mutate values', function(assert) {
  1061. assert.expect(2);
  1062. var objects = [{ 'a': [1, 2] }, { 'a': [3] }],
  1063. actual = fp.mergeAllWith(_.noop, objects);
  1064. assert.deepEqual(objects[0], { 'a': [1, 2] });
  1065. assert.deepEqual(actual, { 'a': [3, 2] });
  1066. });
  1067. }());
  1068. /*--------------------------------------------------------------------------*/
  1069. QUnit.module('fp.mixin');
  1070. (function() {
  1071. var source = { 'a': _.noop };
  1072. QUnit.test('should mixin static methods but not prototype methods', function(assert) {
  1073. assert.expect(2);
  1074. fp.mixin(source);
  1075. assert.strictEqual(typeof fp.a, 'function');
  1076. assert.notOk('a' in fp.prototype);
  1077. delete fp.a;
  1078. delete fp.prototype.a;
  1079. });
  1080. QUnit.test('should not assign inherited `source` methods', function(assert) {
  1081. assert.expect(2);
  1082. function Foo() {}
  1083. Foo.prototype.a = _.noop;
  1084. fp.mixin(new Foo);
  1085. assert.notOk('a' in fp);
  1086. assert.notOk('a' in fp.prototype);
  1087. delete fp.a;
  1088. delete fp.prototype.a;
  1089. });
  1090. QUnit.test('should not remove existing prototype methods', function(assert) {
  1091. assert.expect(2);
  1092. var each1 = fp.each,
  1093. each2 = fp.prototype.each;
  1094. fp.mixin({ 'each': source.a });
  1095. assert.strictEqual(fp.each, source.a);
  1096. assert.strictEqual(fp.prototype.each, each2);
  1097. fp.each = each1;
  1098. fp.prototype.each = each2;
  1099. });
  1100. QUnit.test('should not export to the global when `source` is not an object', function(assert) {
  1101. assert.expect(2);
  1102. var props = _.without(_.keys(_), '_');
  1103. _.times(2, function(index) {
  1104. fp.mixin.apply(fp, index ? [1] : []);
  1105. assert.ok(_.every(props, function(key) {
  1106. return root[key] !== fp[key];
  1107. }));
  1108. _.each(props, function(key) {
  1109. if (root[key] === fp[key]) {
  1110. delete root[key];
  1111. }
  1112. });
  1113. });
  1114. });
  1115. QUnit.test('should convert by name', function(assert) {
  1116. assert.expect(3);
  1117. var object = { 'mixin': convert('mixin', _.mixin) };
  1118. function Foo() {}
  1119. Foo.mixin = object.mixin;
  1120. Foo.mixin(source);
  1121. assert.ok('a' in Foo);
  1122. assert.notOk('a' in Foo.prototype);
  1123. object.mixin(source);
  1124. assert.ok('a' in object);
  1125. });
  1126. }());
  1127. /*--------------------------------------------------------------------------*/
  1128. QUnit.module('fp.nthArg');
  1129. (function() {
  1130. QUnit.test('should return a curried function', function(assert) {
  1131. assert.expect(2);
  1132. var func = fp.nthArg(1);
  1133. assert.strictEqual(func(1)(2), 2);
  1134. func = fp.nthArg(-1);
  1135. assert.strictEqual(func(1), 1);
  1136. });
  1137. }());
  1138. /*--------------------------------------------------------------------------*/
  1139. QUnit.module('fp.over');
  1140. (function() {
  1141. QUnit.test('should not cap iteratee args', function(assert) {
  1142. assert.expect(2);
  1143. _.each([fp.over, convert('over', _.over)], function(func) {
  1144. var over = func([Math.max, Math.min]);
  1145. assert.deepEqual(over(1, 2, 3, 4), [4, 1]);
  1146. });
  1147. });
  1148. }());
  1149. /*--------------------------------------------------------------------------*/
  1150. QUnit.module('fp.omitBy and fp.pickBy');
  1151. _.each(['omitBy', 'pickBy'], function(methodName) {
  1152. var func = fp[methodName];
  1153. QUnit.test('`fp.' + methodName + '` should provide `value` and `key` to `iteratee`', function(assert) {
  1154. assert.expect(1);
  1155. var args;
  1156. func(function() {
  1157. args || (args = slice.call(arguments));
  1158. })({ 'a': 1 });
  1159. assert.deepEqual(args, [1, 'a']);
  1160. });
  1161. });
  1162. /*--------------------------------------------------------------------------*/
  1163. QUnit.module('padChars methods');
  1164. _.each(['padChars', 'padCharsStart', 'padCharsEnd'], function(methodName) {
  1165. var func = fp[methodName],
  1166. isPad = methodName == 'padChars',
  1167. isStart = methodName == 'padCharsStart';
  1168. QUnit.test('`_.' + methodName + '` should truncate pad characters to fit the pad length', function(assert) {
  1169. assert.expect(1);
  1170. if (isPad) {
  1171. assert.strictEqual(func('_-')(8)('abc'), '_-abc_-_');
  1172. } else {
  1173. assert.strictEqual(func('_-')(6)('abc'), isStart ? '_-_abc' : 'abc_-_');
  1174. }
  1175. });
  1176. });
  1177. /*--------------------------------------------------------------------------*/
  1178. QUnit.module('partial methods');
  1179. _.each(['partial', 'partialRight'], function(methodName) {
  1180. var func = fp[methodName],
  1181. isPartial = methodName == 'partial';
  1182. QUnit.test('`_.' + methodName + '` should accept an `args` param', function(assert) {
  1183. assert.expect(1);
  1184. var expected = isPartial ? [1, 2, 3] : [0, 1, 2];
  1185. var actual = func(function(a, b, c) {
  1186. return [a, b, c];
  1187. })([1, 2])(isPartial ? 3 : 0);
  1188. assert.deepEqual(actual, expected);
  1189. });
  1190. QUnit.test('`_.' + methodName + '` should convert by name', function(assert) {
  1191. assert.expect(2);
  1192. var expected = isPartial ? [1, 2, 3] : [0, 1, 2],
  1193. par = convert(methodName, _[methodName]),
  1194. ph = par.placeholder;
  1195. var actual = par(function(a, b, c) {
  1196. return [a, b, c];
  1197. })([1, 2])(isPartial ? 3 : 0);
  1198. assert.deepEqual(actual, expected);
  1199. actual = par(function(a, b, c) {
  1200. return [a, b, c];
  1201. })([ph, 2])(isPartial ? 1 : 0, isPartial ? 3 : 1);
  1202. assert.deepEqual(actual, expected);
  1203. });
  1204. });
  1205. /*--------------------------------------------------------------------------*/
  1206. QUnit.module('fp.propertyOf');
  1207. (function() {
  1208. QUnit.test('should be curried', function(assert) {
  1209. assert.expect(2);
  1210. var object = { 'a': 1 };
  1211. assert.strictEqual(fp.propertyOf(object, 'a'), 1);
  1212. assert.strictEqual(fp.propertyOf(object)('a'), 1);
  1213. });
  1214. }());
  1215. /*--------------------------------------------------------------------------*/
  1216. QUnit.module('fp.pull');
  1217. (function() {
  1218. QUnit.test('should not mutate values', function(assert) {
  1219. assert.expect(2);
  1220. var array = [1, 2, 3],
  1221. actual = fp.pull(2)(array);
  1222. assert.deepEqual(array, [1, 2, 3]);
  1223. assert.deepEqual(actual, [1, 3]);
  1224. });
  1225. }());
  1226. /*--------------------------------------------------------------------------*/
  1227. QUnit.module('fp.pullAll');
  1228. (function() {
  1229. QUnit.test('should not mutate values', function(assert) {
  1230. assert.expect(2);
  1231. var array = [1, 2, 3],
  1232. actual = fp.pullAll([1, 3])(array);
  1233. assert.deepEqual(array, [1, 2, 3]);
  1234. assert.deepEqual(actual, [2]);
  1235. });
  1236. }());
  1237. /*--------------------------------------------------------------------------*/
  1238. QUnit.module('fp.pullAt');
  1239. (function() {
  1240. QUnit.test('should not mutate values', function(assert) {
  1241. assert.expect(2);
  1242. var array = [1, 2, 3],
  1243. actual = fp.pullAt([0, 2])(array);
  1244. assert.deepEqual(array, [1, 2, 3]);
  1245. assert.deepEqual(actual, [2]);
  1246. });
  1247. }());
  1248. /*--------------------------------------------------------------------------*/
  1249. QUnit.module('fp.random');
  1250. (function() {
  1251. var array = Array(1000);
  1252. QUnit.test('should support a `min` and `max` argument', function(assert) {
  1253. assert.expect(1);
  1254. var min = 5,
  1255. max = 10;
  1256. assert.ok(_.some(array, function() {
  1257. var result = fp.random(min)(max);
  1258. return result >= min && result <= max;
  1259. }));
  1260. });
  1261. }());
  1262. /*--------------------------------------------------------------------------*/
  1263. QUnit.module('fp.range');
  1264. (function() {
  1265. QUnit.test('should have an argument order of `start` then `end`', function(assert) {
  1266. assert.expect(1);
  1267. assert.deepEqual(fp.range(1)(4), [1, 2, 3]);
  1268. });
  1269. }());
  1270. /*--------------------------------------------------------------------------*/
  1271. QUnit.module('fp.rearg');
  1272. (function() {
  1273. function fn(a, b, c) {
  1274. return [a, b, c];
  1275. }
  1276. QUnit.test('should be curried', function(assert) {
  1277. assert.expect(1);
  1278. var rearged = fp.rearg([1, 2, 0])(fn);
  1279. assert.deepEqual(rearged('c', 'a', 'b'), ['a', 'b', 'c']);
  1280. });
  1281. QUnit.test('should return a curried function', function(assert) {
  1282. assert.expect(1);
  1283. var rearged = fp.rearg([1, 2, 0], fn);
  1284. assert.deepEqual(rearged('c')('a')('b'), ['a', 'b', 'c']);
  1285. });
  1286. }());
  1287. /*--------------------------------------------------------------------------*/
  1288. QUnit.module('reduce methods');
  1289. _.each(['reduce', 'reduceRight'], function(methodName) {
  1290. var func = fp[methodName],
  1291. isReduce = methodName == 'reduce';
  1292. QUnit.test('`_.' + methodName + '` should provide the correct `iteratee` arguments when iterating an array', function(assert) {
  1293. assert.expect(1);
  1294. var args;
  1295. func(function() {
  1296. args || (args = slice.call(arguments));
  1297. })(0)([1, 2, 3]);
  1298. assert.deepEqual(args, isReduce ? [0, 1] : [0, 3]);
  1299. });
  1300. QUnit.test('`_.' + methodName + '` should provide the correct `iteratee` arguments when iterating an object', function(assert) {
  1301. assert.expect(1);
  1302. var args,
  1303. object = { 'a': 1, 'b': 2 },
  1304. isFIFO = _.keys(object)[0] == 'a';
  1305. var expected = isFIFO
  1306. ? (isReduce ? [0, 1] : [0, 2])
  1307. : (isReduce ? [0, 2] : [0, 1]);
  1308. func(function() {
  1309. args || (args = slice.call(arguments));
  1310. })(0)(object);
  1311. assert.deepEqual(args, expected);
  1312. });
  1313. });
  1314. /*--------------------------------------------------------------------------*/
  1315. QUnit.module('fp.remove');
  1316. (function() {
  1317. QUnit.test('should not mutate values', function(assert) {
  1318. assert.expect(2);
  1319. var array = [1, 2, 3],
  1320. actual = fp.remove(fp.eq(2))(array);
  1321. assert.deepEqual(array, [1, 2, 3]);
  1322. assert.deepEqual(actual, [1, 3]);
  1323. });
  1324. }());
  1325. /*--------------------------------------------------------------------------*/
  1326. QUnit.module('fp.restFrom');
  1327. (function() {
  1328. QUnit.test('should accept a `start` param', function(assert) {
  1329. assert.expect(1);
  1330. var actual = fp.restFrom(2)(function() {
  1331. return slice.call(arguments);
  1332. })('a', 'b', 'c', 'd');
  1333. assert.deepEqual(actual, ['a', 'b', ['c', 'd']]);
  1334. });
  1335. }());
  1336. /*--------------------------------------------------------------------------*/
  1337. QUnit.module('fp.reverse');
  1338. (function() {
  1339. QUnit.test('should not mutate values', function(assert) {
  1340. assert.expect(2);
  1341. var array = [1, 2, 3],
  1342. actual = fp.reverse(array);
  1343. assert.deepEqual(array, [1, 2, 3]);
  1344. assert.deepEqual(actual, [3, 2, 1]);
  1345. });
  1346. }());
  1347. /*--------------------------------------------------------------------------*/
  1348. QUnit.module('fp.runInContext');
  1349. (function() {
  1350. QUnit.test('should return a converted lodash instance', function(assert) {
  1351. assert.expect(1);
  1352. assert.strictEqual(typeof fp.runInContext({}).curryN, 'function');
  1353. });
  1354. QUnit.test('should convert by name', function(assert) {
  1355. assert.expect(1);
  1356. var runInContext = convert('runInContext', _.runInContext);
  1357. assert.strictEqual(typeof runInContext({}).curryN, 'function');
  1358. });
  1359. }());
  1360. /*--------------------------------------------------------------------------*/
  1361. QUnit.module('fp.set');
  1362. (function() {
  1363. QUnit.test('should not mutate values', function(assert) {
  1364. assert.expect(2);
  1365. var object = { 'a': { 'b': 2, 'c': 3 } },
  1366. actual = fp.set('a.b')(3)(object);
  1367. assert.deepEqual(object, { 'a': { 'b': 2, 'c': 3 } });
  1368. assert.deepEqual(actual, { 'a': { 'b': 3, 'c': 3 } });
  1369. });
  1370. }());
  1371. /*--------------------------------------------------------------------------*/
  1372. QUnit.module('fp.setWith');
  1373. (function() {
  1374. QUnit.test('should provide the correct `customizer` arguments', function(assert) {
  1375. assert.expect(1);
  1376. var args;
  1377. fp.setWith(function() {
  1378. args || (args = _.map(arguments, _.cloneDeep));
  1379. })('b.c')(2)({ 'a': 1 });
  1380. assert.deepEqual(args, [undefined, 'b', { 'a': 1 }]);
  1381. });
  1382. QUnit.test('should not mutate values', function(assert) {
  1383. assert.expect(2);
  1384. var object = { 'a': { 'b': 2, 'c': 3 } },
  1385. actual = fp.setWith(Object)('d.e')(4)(object);
  1386. assert.deepEqual(object, { 'a': { 'b': 2, 'c': 3 } });
  1387. assert.deepEqual(actual, { 'a': { 'b': 2, 'c': 3 }, 'd': { 'e': 4 } });
  1388. });
  1389. }());
  1390. /*--------------------------------------------------------------------------*/
  1391. QUnit.module('fp.spreadFrom');
  1392. (function() {
  1393. QUnit.test('should accept a `start` param', function(assert) {
  1394. assert.expect(1);
  1395. var actual = fp.spreadFrom(2)(function() {
  1396. return slice.call(arguments);
  1397. })('a', 'b', ['c', 'd']);
  1398. assert.deepEqual(actual, ['a', 'b', 'c', 'd']);
  1399. });
  1400. }());
  1401. /*--------------------------------------------------------------------------*/
  1402. QUnit.module('trimChars methods');
  1403. _.each(['trimChars', 'trimCharsStart', 'trimCharsEnd'], function(methodName, index) {
  1404. var func = fp[methodName],
  1405. parts = [];
  1406. if (index != 2) {
  1407. parts.push('leading');
  1408. }
  1409. if (index != 1) {
  1410. parts.push('trailing');
  1411. }
  1412. parts = parts.join(' and ');
  1413. QUnit.test('`_.' + methodName + '` should remove ' + parts + ' `chars`', function(assert) {
  1414. assert.expect(1);
  1415. var string = '-_-a-b-c-_-',
  1416. expected = (index == 2 ? '-_-' : '') + 'a-b-c' + (index == 1 ? '-_-' : '');
  1417. assert.strictEqual(func('_-')(string), expected);
  1418. });
  1419. });
  1420. /*--------------------------------------------------------------------------*/
  1421. QUnit.module('fp.unionBy');
  1422. (function() {
  1423. QUnit.test('should have an argument order of `iteratee`, `array`, then `other`', function(assert) {
  1424. assert.expect(1);
  1425. var actual = fp.unionBy(Math.floor, [2.1], [1.2, 2.3]);
  1426. assert.deepEqual(actual, [2.1, 1.2]);
  1427. });
  1428. QUnit.test('should provide the correct `iteratee` arguments', function(assert) {
  1429. assert.expect(1);
  1430. var args;
  1431. fp.unionBy(function() {
  1432. args || (args = slice.call(arguments));
  1433. })([2.1], [1.2, 2.3]);
  1434. assert.deepEqual(args, [2.1]);
  1435. });
  1436. }());
  1437. /*--------------------------------------------------------------------------*/
  1438. QUnit.module('fp.unionWith');
  1439. (function() {
  1440. QUnit.test('should have an argument order of `comparator`, `array`, then `values`', function(assert) {
  1441. assert.expect(1);
  1442. var actual = fp.unionWith(fp.eq)([2, 1])([2, 3]);
  1443. assert.deepEqual(actual, [2, 1, 3]);
  1444. });
  1445. QUnit.test('should provide the correct `comparator` arguments', function(assert) {
  1446. assert.expect(1);
  1447. var args;
  1448. fp.unionWith(function() {
  1449. args || (args = slice.call(arguments));
  1450. })([2, 1])([2, 3]);
  1451. assert.deepEqual(args, [1, 2]);
  1452. });
  1453. }());
  1454. /*--------------------------------------------------------------------------*/
  1455. QUnit.module('fp.uniqBy');
  1456. (function() {
  1457. var objects = [{ 'a': 2 }, { 'a': 3 }, { 'a': 1 }, { 'a': 2 }, { 'a': 3 }, { 'a': 1 }];
  1458. QUnit.test('should work with an `iteratee` argument', function(assert) {
  1459. assert.expect(1);
  1460. var expected = objects.slice(0, 3),
  1461. actual = fp.uniqBy(_.property('a'))(objects);
  1462. assert.deepEqual(actual, expected);
  1463. });
  1464. QUnit.test('should provide the correct `iteratee` arguments', function(assert) {
  1465. assert.expect(1);
  1466. var args;
  1467. fp.uniqBy(function() {
  1468. args || (args = slice.call(arguments));
  1469. })(objects);
  1470. assert.deepEqual(args, [objects[0]]);
  1471. });
  1472. }());
  1473. /*--------------------------------------------------------------------------*/
  1474. QUnit.module('fp.uniqWith');
  1475. (function() {
  1476. QUnit.test('should have an argument order of `comparator`, `array`, then `values`', function(assert) {
  1477. assert.expect(1);
  1478. var actual = fp.uniqWith(fp.eq)([2, 1, 2]);
  1479. assert.deepEqual(actual, [2, 1]);
  1480. });
  1481. QUnit.test('should provide the correct `comparator` arguments', function(assert) {
  1482. assert.expect(1);
  1483. var args;
  1484. fp.uniqWith(function() {
  1485. args || (args = slice.call(arguments));
  1486. })([2, 1, 2]);
  1487. assert.deepEqual(args, [1, 2]);
  1488. });
  1489. }());
  1490. /*--------------------------------------------------------------------------*/
  1491. QUnit.module('fp.update');
  1492. (function() {
  1493. QUnit.test('should not convert end of `path` to an object', function(assert) {
  1494. assert.expect(1);
  1495. var actual = fp.update('a.b')(_.identity)({ 'a': { 'b': 1 } });
  1496. assert.strictEqual(typeof actual.a.b, 'number');
  1497. });
  1498. QUnit.test('should not mutate values', function(assert) {
  1499. assert.expect(2);
  1500. var object = { 'a': { 'b': 2, 'c': 3 } },
  1501. actual = fp.update('a.b')(square)(object);
  1502. assert.deepEqual(object, { 'a': { 'b': 2, 'c': 3 } });
  1503. assert.deepEqual(actual, { 'a': { 'b': 4, 'c': 3 } });
  1504. });
  1505. }());
  1506. /*--------------------------------------------------------------------------*/
  1507. QUnit.module('fp.updateWith');
  1508. (function() {
  1509. QUnit.test('should provide the correct `customizer` arguments', function(assert) {
  1510. var args;
  1511. fp.updateWith(function() {
  1512. args || (args = _.map(arguments, _.cloneDeep));
  1513. })('b.c')(_.constant(2))({ 'a': 1 });
  1514. assert.deepEqual(args, [undefined, 'b', { 'a': 1 }]);
  1515. });
  1516. QUnit.test('should not mutate values', function(assert) {
  1517. assert.expect(2);
  1518. var object = { 'a': { 'b': 2, 'c': 3 } },
  1519. actual = fp.updateWith(Object)('d.e')(_.constant(4))(object);
  1520. assert.deepEqual(object, { 'a': { 'b': 2, 'c': 3 } });
  1521. assert.deepEqual(actual, { 'a': { 'b': 2, 'c': 3 }, 'd': { 'e': 4 } });
  1522. });
  1523. }());
  1524. /*--------------------------------------------------------------------------*/
  1525. QUnit.module('fp.unset');
  1526. (function() {
  1527. QUnit.test('should not mutate values', function(assert) {
  1528. assert.expect(2);
  1529. var object = { 'a': { 'b': 2, 'c': 3 } },
  1530. actual = fp.unset('a.b')(object);
  1531. assert.deepEqual(object, { 'a': { 'b': 2, 'c': 3 } });
  1532. assert.deepEqual(actual, { 'a': { 'c': 3 } });
  1533. });
  1534. }());
  1535. /*--------------------------------------------------------------------------*/
  1536. QUnit.module('fp.xorBy');
  1537. (function() {
  1538. QUnit.test('should have an argument order of `iteratee`, `array`, then `other`', function(assert) {
  1539. assert.expect(1);
  1540. var actual = fp.xorBy(Math.floor, [2.1, 1.2], [2.3, 3.4]);
  1541. assert.deepEqual(actual, [1.2, 3.4]);
  1542. });
  1543. QUnit.test('should provide the correct `iteratee` arguments', function(assert) {
  1544. assert.expect(1);
  1545. var args;
  1546. fp.xorBy(function() {
  1547. args || (args = slice.call(arguments));
  1548. })([2.1, 1.2], [2.3, 3.4]);
  1549. assert.deepEqual(args, [2.3]);
  1550. });
  1551. }());
  1552. /*--------------------------------------------------------------------------*/
  1553. QUnit.module('fp.xorWith');
  1554. (function() {
  1555. QUnit.test('should have an argument order of `comparator`, `array`, then `values`', function(assert) {
  1556. assert.expect(1);
  1557. var actual = fp.xorWith(fp.eq)([2, 1])([2, 3]);
  1558. assert.deepEqual(actual, [1, 3]);
  1559. });
  1560. }());
  1561. /*--------------------------------------------------------------------------*/
  1562. QUnit.module('with methods');
  1563. _.each(['differenceWith', 'intersectionWith', 'xorWith'], function(methodName) {
  1564. var func = fp[methodName];
  1565. QUnit.test('`fp.' + methodName + '` should provide the correct `comparator` arguments', function(assert) {
  1566. assert.expect(1);
  1567. var args;
  1568. func(function() {
  1569. args || (args = slice.call(arguments));
  1570. })([2, 1])([2, 3]);
  1571. assert.deepEqual(args, [2, 2]);
  1572. });
  1573. });
  1574. /*--------------------------------------------------------------------------*/
  1575. QUnit.module('fp.zip');
  1576. (function() {
  1577. QUnit.test('should zip together two arrays', function(assert) {
  1578. assert.expect(1);
  1579. assert.deepEqual(fp.zip([1, 2])([3, 4]), [[1, 3], [2, 4]]);
  1580. });
  1581. }());
  1582. /*--------------------------------------------------------------------------*/
  1583. QUnit.module('fp.zipAll');
  1584. (function() {
  1585. QUnit.test('should zip together an array of arrays', function(assert) {
  1586. assert.expect(1);
  1587. assert.deepEqual(fp.zipAll([[1, 2], [3, 4], [5, 6]]), [[1, 3, 5], [2, 4, 6]]);
  1588. });
  1589. }());
  1590. /*--------------------------------------------------------------------------*/
  1591. QUnit.module('fp.zipObject');
  1592. (function() {
  1593. QUnit.test('should zip together key/value arrays into an object', function(assert) {
  1594. assert.expect(1);
  1595. assert.deepEqual(fp.zipObject(['a', 'b'])([1, 2]), { 'a': 1, 'b': 2 });
  1596. });
  1597. }());
  1598. /*--------------------------------------------------------------------------*/
  1599. QUnit.module('fp.zipWith');
  1600. (function() {
  1601. QUnit.test('should zip arrays combining grouped elements with `iteratee`', function(assert) {
  1602. assert.expect(1);
  1603. var array1 = [1, 2, 3],
  1604. array2 = [4, 5, 6],
  1605. actual = fp.zipWith(add)(array1)(array2);
  1606. assert.deepEqual(actual, [5, 7, 9]);
  1607. });
  1608. }());
  1609. /*--------------------------------------------------------------------------*/
  1610. QUnit.config.asyncRetries = 10;
  1611. QUnit.config.hidepassed = true;
  1612. if (!document) {
  1613. QUnit.config.noglobals = true;
  1614. QUnit.load();
  1615. QUnit.start();
  1616. }
  1617. }.call(this));