diff --git a/.travis.yml b/.travis.yml index f598102d0..00a2b89af 100644 --- a/.travis.yml +++ b/.travis.yml @@ -53,6 +53,7 @@ script: - "[ $SAUCE_LABS == true ] || [ $ISTANBUL == true ] || [ $TRAVIS_SECURE_ENV_VARS == false ] || $BIN $OPTION ./test.js ../lodash.min.js" - "[ $SAUCE_LABS == false ] || $BIN ./test/saucelabs.js name=\"lodash tests\" runner=\"test/index.html?build=../lodash.js&noglobals=true\" tags=\"development\"" - "[ $SAUCE_LABS == false ] || $BIN ./test/saucelabs.js name=\"lodash tests\" runner=\"test/index.html?build=../lodash.min.js&noglobals=true\" tags=\"production\"" + - "[ $SAUCE_LABS == false ] || $BIN ./test/saucelabs.js name=\"lodash-fp tests\" runner=\"test/fp.html?noglobals=true\" tags=\"development\"" - "[ $SAUCE_LABS == false ] || $BIN ./test/saucelabs.js name=\"underscore tests\" runner=\"test/underscore.html?build=../lodash.js\" tags=\"development,underscore\"" - "[ $SAUCE_LABS == false ] || $BIN ./test/saucelabs.js name=\"underscore tests\" runner=\"test/underscore.html?build=../lodash.min.js\" tags=\"production,underscore\"" - "[ $SAUCE_LABS == false ] || $BIN ./test/saucelabs.js name=\"backbone tests\" runner=\"test/backbone.html?build=../lodash.js\" tags=\"development,backbone\"" diff --git a/dist/lodash.fp.js b/dist/lodash.fp.js index a6f10d228..432ed6f44 100644 --- a/dist/lodash.fp.js +++ b/dist/lodash.fp.js @@ -86,14 +86,14 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {Function|Object} Returns the converted function or object. */ function baseConvert(util, name, func) { - if (!func) { + if (typeof func != 'function') { func = name; - name = null; + name = undefined; } if (func == null) { throw new TypeError; } - var isLib = name == null && typeof func.VERSION == 'string'; + var isLib = name === undefined && typeof func.VERSION == 'string'; var _ = isLib ? func : { 'ary': util.ary, @@ -264,19 +264,26 @@ return /******/ (function(modules) { // webpackBootstrap // Iterate over methods for the current ary cap. var pairs = []; each(mapping.caps, function(cap) { - each(mapping.aryMethodMap[cap], function(name) { - var func = _[mapping.keyMap[name] || name]; + each(mapping.aryMethodMap[cap], function(key) { + var func = _[mapping.keyMap[key] || key]; if (func) { - // Wrap the lodash method and its aliases. - var wrapped = wrap(name, func); - pairs.push([name, wrapped]); - each(mapping.aliasMap[name] || [], function(alias) { pairs.push([alias, wrapped]); }); + pairs.push([key, wrap(key, func)]); } }); }); // Assign to `_` leaving `_.prototype` unchanged to allow chaining. - each(pairs, function(pair) { _[pair[0]] = pair[1]; }); + each(pairs, function(pair) { + _[pair[0]] = pair[1]; + }); + + // Wrap the lodash method and its aliases. + each(keys(_), function(key) { + each(mapping.aliasMap[key] || [], function(alias) { + _[alias] = _[key]; + }); + }); + return _; } @@ -291,9 +298,33 @@ return /******/ (function(modules) { // webpackBootstrap /** Used to map method names to their aliases. */ 'aliasMap': { + 'ary': ['nAry'], + 'conj': ['allPass'], + 'disj': ['somePass'], + 'filter': ['whereEq'], + 'flatten': ['unnest'], + 'flow': ['pipe'], + 'flowRight': ['compose'], 'forEach': ['each'], 'forEachRight': ['eachRight'], - 'head': ['first'] + 'get': ['path'], + 'getOr': ['pathOr'], + 'head': ['first'], + 'includes': ['contains'], + 'initial': ['init'], + 'isEqual': ['equals'], + 'mapValues': ['mapObj'], + 'matchesProperty': ['pathEq'], + 'modArgs': ['useWith'], + 'modArgsSet': ['converge'], + 'omit': ['dissoc', 'omitAll'], + 'pick': ['pickAll'], + 'property': ['prop'], + 'propertyOf': ['propOf'], + 'rest': ['unapply'], + 'some': ['all'], + 'spread': ['apply'], + 'zipObject': ['zipObj'] }, /** Used to map method names to their iteratee ary. */ @@ -312,6 +343,7 @@ return /******/ (function(modules) { // webpackBootstrap 'findLast': 1, 'findLastIndex': 1, 'findLastKey': 1, + 'flatMap': 1, 'forEach': 1, 'forEachRight': 1, 'forIn': 1, @@ -338,24 +370,26 @@ return /******/ (function(modules) { // webpackBootstrap /** Used to map ary to method names. */ 'aryMethodMap': { 1: ( - 'attempt,ceil,create,curry,floor,iteratee,invert,memoize,method,methodOf,' + - 'mixin,rest,reverse,round,runInContext,template,trim,trimLeft,trimRight,' + - 'words,zipObject').split(','), + 'attempt,ceil,create,curry,floor,fromPairs,iteratee,invert,over,overEvery,' + + 'overSome,memoize,method,methodOf,mixin,rest,reverse,round,runInContext,template,' + + 'trim,trimLeft,trimRight,uniqueId,words').split(','), 2: ( - 'ary,assign,at,bind,bindKey,cloneDeepWith,cloneWith,countBy,curryN,debounce,' + - 'defaults,defaultsDeep,delay,difference,drop,dropRight,dropRightWhile,' + + 'add,ary,assign,at,bind,bindKey,cloneDeepWith,cloneWith,concat,countBy,curryN,' + + 'debounce,defaults,defaultsDeep,delay,difference,drop,dropRight,dropRightWhile,' + 'dropWhile,endsWith,every,extend,filter,find,find,findIndex,findKey,findLast,' + - 'findLastIndex,findLastKey,forEach,forEachRight,forIn,forInRight,forOwn,' + - 'forOwnRight,get,groupBy,includes,indexBy,indexOf,intersection,invoke,' + - 'isMatch,lastIndexOf,map,mapKeys,mapValues,maxBy,minBy,merge,omit,pad,padLeft,' + - 'padRight,parseInt,partition,pick,pull,pullAll,pullAt,random,range,rearg,reject,' + + 'findLastIndex,findLastKey,flatMap,forEach,forEachRight,forIn,forInRight,' + + 'forOwn,forOwnRight,get,groupBy,includes,indexBy,indexOf,intersection,' + + 'invoke,invokeMap,isMatch,lastIndexOf,map,mapKeys,mapValues,matchesProperty,' + + 'maxBy,mean,minBy,merge,modArgs,modArgsSet,omit,pad,padLeft,padRight,parseInt,' + + 'partition,pick,pull,pullAll,pullAt,random,range,rangeRight,rearg,reject,' + 'remove,repeat,result,sampleSize,set,some,sortBy,sortByOrder,sortedIndexBy,' + - 'sortedLastIndexBy,sortedUniqBy,startsWith,sumBy,take,takeRight,takeRightWhile,' + - 'takeWhile,throttle,times,trunc,union,uniqBy,uniqueId,without,wrap,xor,zip').split(','), + 'sortedLastIndexBy,sortedUniqBy,startsWith,subtract,sumBy,take,takeRight,' + + 'takeRightWhile,takeWhile,throttle,times,truncate,union,uniqBy,without,wrap,' + + 'xor,zip,zipObject').split(','), 3: ( - 'assignWith,clamp,differenceBy,extendWith,inRange,intersectionBy,isEqualWith,' + - 'isMatchWith,mergeWith,omitBy,pickBy,pullAllBy,reduce,reduceRight,slice,' + - 'transform,unionBy,xorBy,zipWith').split(','), + 'assignWith,clamp,differenceBy,extendWith,getOr,inRange,intersectionBy,' + + 'isEqualWith,isMatchWith,mergeWith,omitBy,pickBy,pullAllBy,reduce,' + + 'reduceRight,slice,transform,unionBy,xorBy,zipWith').split(','), 4: ['fill'] }, @@ -377,14 +411,13 @@ return /******/ (function(modules) { // webpackBootstrap }, /** Used to iterate `mapping.aryMethodMap` keys. */ - 'caps': ['1', '2', '3', '4'], + 'caps': [1, 2, 3, 4], /** Used to map keys to other keys. */ 'keyMap': { 'curryN': 'curry', 'curryRightN': 'curryRight', - 'debounceOpt': 'debounce', - 'throttleOpt': 'throttle' + 'getOr': 'get' }, /** Used to identify methods which mutate arrays or objects. */ @@ -413,8 +446,11 @@ return /******/ (function(modules) { // webpackBootstrap /** Used to track methods that skip `_.rearg`. */ 'skipReargMap': { 'difference': true, + 'matchesProperty': true, 'random': true, 'range': true, + 'rangeRight': true, + 'zip': true, 'zipObject': true } }; diff --git a/dist/lodash.fp.min.js b/dist/lodash.fp.min.js index edada6f2c..747b41dc5 100644 --- a/dist/lodash.fp.min.js +++ b/dist/lodash.fp.min.js @@ -1 +1 @@ -!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.fp=t():e.fp=t()}(this,function(){return function(e){function t(n){if(r[n])return r[n].exports;var i=r[n]={exports:{},id:n,loaded:!1};return e[n].call(i.exports,i,i.exports,t),i.loaded=!0,i.exports}var r={};return t.m=e,t.c=r,t.p="",t(0)}([function(e,t,r){function n(e){return i(e,e)}var i=r(1);e.exports=n},function(e,t,r){function n(e,t,r){if(r||(r=t,t=null),null==r)throw new TypeError;var o=null==t&&"string"==typeof r.VERSION,u=o?r:{ary:e.ary,curry:e.curry,forEach:e.forEach,isFunction:e.isFunction,iteratee:e.iteratee,keys:e.keys,rearg:e.rearg},p=u.ary,f=u.curry,c=u.forEach,s=u.isFunction,l=u.keys,d=u.rearg,h=function(e,t){return function(){var r=arguments,n=Math.min(r.length,t);switch(n){case 1:return e(r[0]);case 2:return e(r[0],r[1])}for(r=Array(n);n--;)r[n]=arguments[n];return e.apply(void 0,r)}},y=function(e){return function(){for(var t=-1,r=arguments.length,n=Array(r);r--;)n[r]=arguments[r];var i=n[0];for(r=i?i.length:0,n[0]=Array(r);++t2?r-2:1,t=e(t);var n=t.length;return r>=n?t:h(t,r)}},mixin:function(e){return function(t){var r=this;if(!s(r))return e(r,Object(t));var n=[],i=[];return c(l(t),function(e){var a=t[e];s(a)&&(i.push(e),n.push(r.prototype[e]))}),e(r,Object(t)),c(i,function(e,t){var i=n[t];s(i)?r.prototype[e]=i:delete r.prototype[e]}),r}},runInContext:function(t){return function(r){return n(e,t(r))}}},x=function(e,t){var r=v[e];if(r)return r(t);a.array[e]?t=y(t):a.object[e]&&(t=g(t));var n;return c(i.caps,function(r){return c(i.aryMethodMap[r],function(a){if(e==a){n=p(t,r),r>1&&!i.skipReargMap[e]&&(n=d(n,i.methodReargMap[e]||i.aryReargMap[r]));var u=!o&&i.aryIterateeMap[e];return u&&(n=m(n,u)),r>1&&(n=f(n,r)),!1}}),!n}),n||t};if(!o)return x(t,r);var R=[];return c(i.caps,function(e){c(i.aryMethodMap[e],function(e){var t=u[i.keyMap[e]||e];if(t){var r=x(e,t);R.push([e,r]),c(i.aliasMap[e]||[],function(e){R.push([e,r])})}})}),c(R,function(e){u[e[0]]=e[1]}),u}var i=r(2),a=i.mutateMap;e.exports=n},function(e,t){e.exports={aliasMap:{forEach:["each"],forEachRight:["eachRight"],head:["first"]},aryIterateeMap:{assignWith:2,cloneDeepWith:1,cloneWith:1,dropRightWhile:1,dropWhile:1,every:1,extendWith:2,filter:1,find:1,findIndex:1,findKey:1,findLast:1,findLastIndex:1,findLastKey:1,forEach:1,forEachRight:1,forIn:1,forInRight:1,forOwn:1,forOwnRight:1,isEqualWith:2,isMatchWith:2,map:1,mapKeys:1,mapValues:1,partition:1,reduce:2,reduceRight:2,reject:1,remove:1,some:1,takeRightWhile:1,takeWhile:1,times:1,transform:2},aryMethodMap:{1:"attempt,ceil,create,curry,floor,iteratee,invert,memoize,method,methodOf,mixin,rest,reverse,round,runInContext,template,trim,trimLeft,trimRight,words,zipObject".split(","),2:"ary,assign,at,bind,bindKey,cloneDeepWith,cloneWith,countBy,curryN,debounce,defaults,defaultsDeep,delay,difference,drop,dropRight,dropRightWhile,dropWhile,endsWith,every,extend,filter,find,find,findIndex,findKey,findLast,findLastIndex,findLastKey,forEach,forEachRight,forIn,forInRight,forOwn,forOwnRight,get,groupBy,includes,indexBy,indexOf,intersection,invoke,isMatch,lastIndexOf,map,mapKeys,mapValues,maxBy,minBy,merge,omit,pad,padLeft,padRight,parseInt,partition,pick,pull,pullAll,pullAt,random,range,rearg,reject,remove,repeat,result,sampleSize,set,some,sortBy,sortByOrder,sortedIndexBy,sortedLastIndexBy,sortedUniqBy,startsWith,sumBy,take,takeRight,takeRightWhile,takeWhile,throttle,times,trunc,union,uniqBy,uniqueId,without,wrap,xor,zip".split(","),3:"assignWith,clamp,differenceBy,extendWith,inRange,intersectionBy,isEqualWith,isMatchWith,mergeWith,omitBy,pickBy,pullAllBy,reduce,reduceRight,slice,transform,unionBy,xorBy,zipWith".split(","),4:["fill"]},aryReargMap:{2:[1,0],3:[2,1,0],4:[3,2,0,1]},methodReargMap:{clamp:[2,0,1],reduce:[2,0,1],reduceRight:[2,0,1],slice:[2,0,1],transform:[2,0,1]},caps:["1","2","3","4"],keyMap:{curryN:"curry",curryRightN:"curryRight",debounceOpt:"debounce",throttleOpt:"throttle"},mutateMap:{array:{fill:!0,pull:!0,pullAll:!0,pullAllBy:!0,pullAt:!0,remove:!0,reverse:!0},object:{assign:!0,assignWith:!0,defaults:!0,defaultsDeep:!0,extend:!0,extendWith:!0,merge:!0,mergeWith:!0}},skipReargMap:{difference:!0,random:!0,range:!0,zipObject:!0}}}])}); \ No newline at end of file +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.fp=t():e.fp=t()}(this,function(){return function(e){function t(n){if(r[n])return r[n].exports;var i=r[n]={exports:{},id:n,loaded:!1};return e[n].call(i.exports,i,i.exports,t),i.loaded=!0,i.exports}var r={};return t.m=e,t.c=r,t.p="",t(0)}([function(e,t,r){function n(e){return i(e,e)}var i=r(1);e.exports=n},function(e,t,r){function n(e,t,r){if("function"!=typeof r&&(r=t,t=void 0),null==r)throw new TypeError;var o=void 0===t&&"string"==typeof r.VERSION,p=o?r:{ary:e.ary,curry:e.curry,forEach:e.forEach,isFunction:e.isFunction,iteratee:e.iteratee,keys:e.keys,rearg:e.rearg},u=p.ary,s=p.curry,c=p.forEach,f=p.isFunction,l=p.keys,d=p.rearg,h=function(e,t){return function(){var r=arguments,n=Math.min(r.length,t);switch(n){case 1:return e(r[0]);case 2:return e(r[0],r[1])}for(r=Array(n);n--;)r[n]=arguments[n];return e.apply(void 0,r)}},y=function(e){return function(){for(var t=-1,r=arguments.length,n=Array(r);r--;)n[r]=arguments[r];var i=n[0];for(r=i?i.length:0,n[0]=Array(r);++t2?r-2:1,t=e(t);var n=t.length;return r>=n?t:h(t,r)}},mixin:function(e){return function(t){var r=this;if(!f(r))return e(r,Object(t));var n=[],i=[];return c(l(t),function(e){var a=t[e];f(a)&&(i.push(e),n.push(r.prototype[e]))}),e(r,Object(t)),c(i,function(e,t){var i=n[t];f(i)?r.prototype[e]=i:delete r.prototype[e]}),r}},runInContext:function(t){return function(r){return n(e,t(r))}}},x=function(e,t){var r=v[e];if(r)return r(t);a.array[e]?t=y(t):a.object[e]&&(t=g(t));var n;return c(i.caps,function(r){return c(i.aryMethodMap[r],function(a){if(e==a){n=u(t,r),r>1&&!i.skipReargMap[e]&&(n=d(n,i.methodReargMap[e]||i.aryReargMap[r]));var p=!o&&i.aryIterateeMap[e];return p&&(n=m(n,p)),r>1&&(n=s(n,r)),!1}}),!n}),n||t};if(!o)return x(t,r);var R=[];return c(i.caps,function(e){c(i.aryMethodMap[e],function(e){var t=p[i.keyMap[e]||e];t&&R.push([e,x(e,t)])})}),c(R,function(e){p[e[0]]=e[1]}),c(l(p),function(e){c(i.aliasMap[e]||[],function(t){p[t]=p[e]})}),p}var i=r(2),a=i.mutateMap;e.exports=n},function(e,t){e.exports={aliasMap:{ary:["nAry"],conj:["allPass"],disj:["somePass"],filter:["whereEq"],flatten:["unnest"],flow:["pipe"],flowRight:["compose"],forEach:["each"],forEachRight:["eachRight"],get:["path"],getOr:["pathOr"],head:["first"],includes:["contains"],initial:["init"],isEqual:["equals"],mapValues:["mapObj"],matchesProperty:["pathEq"],modArgs:["useWith"],modArgsSet:["converge"],omit:["dissoc","omitAll"],pick:["pickAll"],property:["prop"],propertyOf:["propOf"],rest:["unapply"],some:["all"],spread:["apply"],zipObject:["zipObj"]},aryIterateeMap:{assignWith:2,cloneDeepWith:1,cloneWith:1,dropRightWhile:1,dropWhile:1,every:1,extendWith:2,filter:1,find:1,findIndex:1,findKey:1,findLast:1,findLastIndex:1,findLastKey:1,flatMap:1,forEach:1,forEachRight:1,forIn:1,forInRight:1,forOwn:1,forOwnRight:1,isEqualWith:2,isMatchWith:2,map:1,mapKeys:1,mapValues:1,partition:1,reduce:2,reduceRight:2,reject:1,remove:1,some:1,takeRightWhile:1,takeWhile:1,times:1,transform:2},aryMethodMap:{1:"attempt,ceil,create,curry,floor,fromPairs,iteratee,invert,over,overEvery,overSome,memoize,method,methodOf,mixin,rest,reverse,round,runInContext,template,trim,trimLeft,trimRight,uniqueId,words".split(","),2:"add,ary,assign,at,bind,bindKey,cloneDeepWith,cloneWith,concat,countBy,curryN,debounce,defaults,defaultsDeep,delay,difference,drop,dropRight,dropRightWhile,dropWhile,endsWith,every,extend,filter,find,find,findIndex,findKey,findLast,findLastIndex,findLastKey,flatMap,forEach,forEachRight,forIn,forInRight,forOwn,forOwnRight,get,groupBy,includes,indexBy,indexOf,intersection,invoke,invokeMap,isMatch,lastIndexOf,map,mapKeys,mapValues,matchesProperty,maxBy,mean,minBy,merge,modArgs,modArgsSet,omit,pad,padLeft,padRight,parseInt,partition,pick,pull,pullAll,pullAt,random,range,rangeRight,rearg,reject,remove,repeat,result,sampleSize,set,some,sortBy,sortByOrder,sortedIndexBy,sortedLastIndexBy,sortedUniqBy,startsWith,subtract,sumBy,take,takeRight,takeRightWhile,takeWhile,throttle,times,truncate,union,uniqBy,without,wrap,xor,zip,zipObject".split(","),3:"assignWith,clamp,differenceBy,extendWith,getOr,inRange,intersectionBy,isEqualWith,isMatchWith,mergeWith,omitBy,pickBy,pullAllBy,reduce,reduceRight,slice,transform,unionBy,xorBy,zipWith".split(","),4:["fill"]},aryReargMap:{2:[1,0],3:[2,1,0],4:[3,2,0,1]},methodReargMap:{clamp:[2,0,1],reduce:[2,0,1],reduceRight:[2,0,1],slice:[2,0,1],transform:[2,0,1]},caps:[1,2,3,4],keyMap:{curryN:"curry",curryRightN:"curryRight",getOr:"get"},mutateMap:{array:{fill:!0,pull:!0,pullAll:!0,pullAllBy:!0,pullAt:!0,remove:!0,reverse:!0},object:{assign:!0,assignWith:!0,defaults:!0,defaultsDeep:!0,extend:!0,extendWith:!0,merge:!0,mergeWith:!0}},skipReargMap:{difference:!0,matchesProperty:!0,random:!0,range:!0,rangeRight:!0,zip:!0,zipObject:!0}}}])}); \ No newline at end of file diff --git a/dist/mapping.fp.js b/dist/mapping.fp.js new file mode 100644 index 000000000..a591a2bd6 --- /dev/null +++ b/dist/mapping.fp.js @@ -0,0 +1,222 @@ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define([], factory); + else if(typeof exports === 'object') + exports["mapping"] = factory(); + else + root["mapping"] = factory(); +})(this, function() { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; + +/******/ // The require function +/******/ function __webpack_require__(moduleId) { + +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) +/******/ return installedModules[moduleId].exports; + +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ exports: {}, +/******/ id: moduleId, +/******/ loaded: false +/******/ }; + +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); + +/******/ // Flag the module as loaded +/******/ module.loaded = true; + +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } + + +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; + +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; + +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; + +/******/ // Load entry module and return exports +/******/ return __webpack_require__(0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ function(module, exports) { + + module.exports = { + + /** Used to map method names to their aliases. */ + 'aliasMap': { + 'ary': ['nAry'], + 'conj': ['allPass'], + 'disj': ['somePass'], + 'filter': ['whereEq'], + 'flatten': ['unnest'], + 'flow': ['pipe'], + 'flowRight': ['compose'], + 'forEach': ['each'], + 'forEachRight': ['eachRight'], + 'get': ['path'], + 'getOr': ['pathOr'], + 'head': ['first'], + 'includes': ['contains'], + 'initial': ['init'], + 'isEqual': ['equals'], + 'mapValues': ['mapObj'], + 'matchesProperty': ['pathEq'], + 'modArgs': ['useWith'], + 'modArgsSet': ['converge'], + 'omit': ['dissoc', 'omitAll'], + 'pick': ['pickAll'], + 'property': ['prop'], + 'propertyOf': ['propOf'], + 'rest': ['unapply'], + 'some': ['all'], + 'spread': ['apply'], + 'zipObject': ['zipObj'] + }, + + /** Used to map method names to their iteratee ary. */ + 'aryIterateeMap': { + 'assignWith': 2, + 'cloneDeepWith': 1, + 'cloneWith': 1, + 'dropRightWhile': 1, + 'dropWhile': 1, + 'every': 1, + 'extendWith': 2, + 'filter': 1, + 'find': 1, + 'findIndex': 1, + 'findKey': 1, + 'findLast': 1, + 'findLastIndex': 1, + 'findLastKey': 1, + 'flatMap': 1, + 'forEach': 1, + 'forEachRight': 1, + 'forIn': 1, + 'forInRight': 1, + 'forOwn': 1, + 'forOwnRight': 1, + 'isEqualWith': 2, + 'isMatchWith': 2, + 'map': 1, + 'mapKeys': 1, + 'mapValues': 1, + 'partition': 1, + 'reduce': 2, + 'reduceRight': 2, + 'reject': 1, + 'remove': 1, + 'some': 1, + 'takeRightWhile': 1, + 'takeWhile': 1, + 'times': 1, + 'transform': 2 + }, + + /** Used to map ary to method names. */ + 'aryMethodMap': { + 1: ( + 'attempt,ceil,create,curry,floor,fromPairs,iteratee,invert,over,overEvery,' + + 'overSome,memoize,method,methodOf,mixin,rest,reverse,round,runInContext,template,' + + 'trim,trimLeft,trimRight,uniqueId,words').split(','), + 2: ( + 'add,ary,assign,at,bind,bindKey,cloneDeepWith,cloneWith,concat,countBy,curryN,' + + 'debounce,defaults,defaultsDeep,delay,difference,drop,dropRight,dropRightWhile,' + + 'dropWhile,endsWith,every,extend,filter,find,find,findIndex,findKey,findLast,' + + 'findLastIndex,findLastKey,flatMap,forEach,forEachRight,forIn,forInRight,' + + 'forOwn,forOwnRight,get,groupBy,includes,indexBy,indexOf,intersection,' + + 'invoke,invokeMap,isMatch,lastIndexOf,map,mapKeys,mapValues,matchesProperty,' + + 'maxBy,mean,minBy,merge,modArgs,modArgsSet,omit,pad,padLeft,padRight,parseInt,' + + 'partition,pick,pull,pullAll,pullAt,random,range,rangeRight,rearg,reject,' + + 'remove,repeat,result,sampleSize,set,some,sortBy,sortByOrder,sortedIndexBy,' + + 'sortedLastIndexBy,sortedUniqBy,startsWith,subtract,sumBy,take,takeRight,' + + 'takeRightWhile,takeWhile,throttle,times,truncate,union,uniqBy,without,wrap,' + + 'xor,zip,zipObject').split(','), + 3: ( + 'assignWith,clamp,differenceBy,extendWith,getOr,inRange,intersectionBy,' + + 'isEqualWith,isMatchWith,mergeWith,omitBy,pickBy,pullAllBy,reduce,' + + 'reduceRight,slice,transform,unionBy,xorBy,zipWith').split(','), + 4: + ['fill'] + }, + + /** Used to map ary to rearg configs by method ary. */ + 'aryReargMap': { + 2: [1, 0], + 3: [2, 1, 0], + 4: [3, 2, 0, 1] + }, + + /** Used to map ary to rearg configs by method names. */ + 'methodReargMap': { + 'clamp': [2, 0, 1], + 'reduce': [2, 0, 1], + 'reduceRight': [2, 0, 1], + 'slice': [2, 0, 1], + 'transform': [2, 0, 1] + }, + + /** Used to iterate `mapping.aryMethodMap` keys. */ + 'caps': [1, 2, 3, 4], + + /** Used to map keys to other keys. */ + 'keyMap': { + 'curryN': 'curry', + 'curryRightN': 'curryRight', + 'getOr': 'get' + }, + + /** Used to identify methods which mutate arrays or objects. */ + 'mutateMap': { + 'array': { + 'fill': true, + 'pull': true, + 'pullAll': true, + 'pullAllBy': true, + 'pullAt': true, + 'remove': true, + 'reverse': true + }, + 'object': { + 'assign': true, + 'assignWith': true, + 'defaults': true, + 'defaultsDeep': true, + 'extend': true, + 'extendWith': true, + 'merge': true, + 'mergeWith': true + } + }, + + /** Used to track methods that skip `_.rearg`. */ + 'skipReargMap': { + 'difference': true, + 'matchesProperty': true, + 'random': true, + 'range': true, + 'rangeRight': true, + 'zip': true, + 'zipObject': true + } + }; + + +/***/ } +/******/ ]) +}); +; \ No newline at end of file diff --git a/lib/fp/build.js b/lib/fp/build.js index f4c5237ca..2ee8923f7 100644 --- a/lib/fp/build.js +++ b/lib/fp/build.js @@ -30,7 +30,7 @@ var mappingConfig = { 'entry': path.join(__dirname, 'mapping.js'), 'output': { 'path': distPath, - 'filename': 'fp-mapping.js', + 'filename': 'mapping.fp.js', 'library': 'mapping', 'libraryTarget': 'umd' } diff --git a/test/fp.html b/test/fp.html new file mode 100644 index 000000000..5d7cfe248 --- /dev/null +++ b/test/fp.html @@ -0,0 +1,42 @@ + + + + + lodash-fp Test Suite + + + + + + + + + + + + +
+ + + diff --git a/test/test-fp.js b/test/test-fp.js index 8491b12be..8f278e18f 100644 --- a/test/test-fp.js +++ b/test/test-fp.js @@ -1,744 +1,809 @@ -'use strict'; +;(function() { -var _ = require('lodash'), - path = require('path'); + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; -var basePath = path.join(__dirname, '..'), - libPath = path.join(basePath, 'lib'), - fpPath = path.join(libPath, 'fp'); + /** Used as the size to cover large array optimizations. */ + var LARGE_ARRAY_SIZE = 200; -var convert = require(path.join(fpPath, 'fp.js')), - mapping = require(path.join(fpPath, 'mapping.js')); + /** Used as a reference to the global object. */ + var root = (typeof global == 'object' && global) || this; -var fp = convert(_.runInContext()); + /** Used for native method references. */ + var arrayProto = Array.prototype; -global.QUnit = require('qunitjs'); -require('qunit-extras').runInContext(global); + /** Method and object shortcuts. */ + var phantom = root.phantom, + amd = root.define && define.amd, + document = !phantom && root.document, + noop = function() {}, + slice = arrayProto.slice; -/*----------------------------------------------------------------------------*/ + /*--------------------------------------------------------------------------*/ -/** Used as the size to cover large array optimizations. */ -var LARGE_ARRAY_SIZE = 200; + /** Use a single "load" function. */ + var load = (!amd && typeof require == 'function') + ? require + : noop; -/** Used for native method references. */ -var arrayProto = Array.prototype; + /** The unit testing framework. */ + var QUnit = root.QUnit || (root.QUnit = ( + QUnit = load('../node_modules/qunitjs/qunit/qunit.js') || root.QUnit, + QUnit = QUnit.QUnit || QUnit + )); -/** Method and object shortcuts. */ -var slice = arrayProto.slice; + /** Load stable Lodash and QUnit Extras. */ + var _ = root._ || load('../lodash.js'); + if (_) { + _ = _.runInContext(root); + } + var QUnitExtras = load('../node_modules/qunit-extras/qunit-extras.js'); + if (QUnitExtras) { + QUnitExtras.runInContext(root); + } -/*----------------------------------------------------------------------------*/ + var convert = root.fp || load('../dist/lodash.fp.js'), + mapping = root.mapping || load('../lib/fp/mapping.js'), + fp = convert(_.runInContext()); -QUnit.module('method aliases'); + /*--------------------------------------------------------------------------*/ -(function() { - QUnit.test('should have correct aliases', function(assert) { - assert.expect(1); + /** + * 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 skipTest(assert, count) { + count || (count = 1); + while (count--) { + assert.ok(true, 'test skipped'); + } + } - var actual = _.transform(mapping.aliasMap, function(result, aliases, methodName) { - var func = fp[methodName]; - _.each(aliases, function(alias) { - result.push([alias, fp[alias] === func]); + /*--------------------------------------------------------------------------*/ + + QUnit.module('method aliases'); + + (function() { + QUnit.test('should have correct aliases', function(assert) { + assert.expect(1); + + var actual = _.transform(mapping.aliasMap, function(result, aliases, methodName) { + var func = fp[methodName]; + _.each(aliases, function(alias) { + result.push([alias, fp[alias] === func]); + }); + }, []); + + 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', 'restParam', 'runInContext' + ]; + + var exceptions = funcMethods.concat('mixin', 'template'), + expected = _.map(mapping.aryMethodMap[1], _.constant(true)); + + var actual = _.map(mapping.aryMethodMap[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(_.reject(actual, 1), []); - }); -}()); + assert.deepEqual(actual, expected); + }); -/*----------------------------------------------------------------------------*/ + QUnit.test('should have a cap of 2', function(assert) { + assert.expect(1); -QUnit.module('method ary caps'); + var funcMethods = [ + 'after', 'ary', 'before', 'bind', 'bindKey', 'cloneDeepWith', 'cloneWith', + 'curryN', 'debounce', 'delay', 'modArgs', 'modArgsSet', 'rearg', 'throttle', + 'wrap' + ]; -(function() { - QUnit.test('should have a cap of 1', function(assert) { - assert.expect(1); + var exceptions = _.difference(funcMethods.concat('matchesProperty'), ['cloneDeepWith', 'cloneWith', 'delay']), + expected = _.map(mapping.aryMethodMap[2], _.constant(true)); - var funcMethods = [ - 'curry', 'iteratee', 'memoize', 'over', 'overEvery', 'overSome', - 'method', 'methodOf', 'restParam', 'runInContext' - ]; + var actual = _.map(mapping.aryMethodMap[2], function(methodName) { + var args = _.includes(funcMethods, methodName) ? [methodName == 'curryN' ? 1 : _.noop, _.noop] : [1, []], + result = _.attempt(function() { return fp[methodName](args[0])(args[1]); }); - var exceptions = funcMethods.concat('mixin', 'template'), - expected = _.map(mapping.aryMethodMap[1], _.constant(true)); + if (_.includes(exceptions, methodName) + ? typeof result == 'function' + : typeof result != 'function' + ) { + return true; + } + console.log(methodName, result); + return false; + }); - var actual = _.map(mapping.aryMethodMap[1], function(methodName) { - var arg = _.includes(funcMethods, methodName) ? _.noop : 1, - result = _.attempt(function() { return fp[methodName](arg); }); + assert.deepEqual(actual, expected); + }); - if (_.includes(exceptions, methodName) - ? typeof result == 'function' - : typeof result != 'function' - ) { - return true; + QUnit.test('should have a cap of 3', function(assert) { + assert.expect(1); + + var funcMethods = [ + 'assignWith', 'extendWith', 'isEqualWith', 'isMatchWith', 'omitBy', + 'pickBy', 'reduce', 'reduceRight', 'transform', 'zipWith' + ]; + + var expected = _.map(mapping.aryMethodMap[3], _.constant(true)); + + var actual = _.map(mapping.aryMethodMap[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', 'b', 'd'], + 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('b', 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(1); + + if (!document) { + var args, + array = [1, 2, 3], + map = convert('map', _.map); + + map(function() { + args || (args = slice.call(arguments)); + })(array); + + assert.deepEqual(args, [1]); } - 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', 'cloneDeepWith', 'cloneWith', - 'curryN', 'debounce', 'delay', 'modArgs', 'modArgsSet', 'rearg', 'throttle', - 'wrap' - ]; - - var exceptions = _.difference(funcMethods.concat('matchesProperty'), ['cloneDeepWith', 'cloneWith', 'delay']), - expected = _.map(mapping.aryMethodMap[2], _.constant(true)); - - var actual = _.map(mapping.aryMethodMap[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; + else { + skipTest(assert); } - console.log(methodName, result); - return false; }); - assert.deepEqual(actual, expected); - }); + QUnit.test('should not support shortcut fusion', function(assert) { + assert.expect(3); - QUnit.test('should have a cap of 3', function(assert) { - assert.expect(1); + if (!document) { + var array = fp.range(0, LARGE_ARRAY_SIZE), + filterCount = 0, + mapCount = 0; - var funcMethods = [ - 'assignWith', 'extendWith', 'isEqualWith', 'isMatchWith', 'omitBy', - 'pickBy', 'reduce', 'reduceRight', 'transform', 'zipWith' - ]; + var iteratee = function(value) { + mapCount++; + return value * value; + }; - var expected = _.map(mapping.aryMethodMap[3], _.constant(true)); + var predicate = function(value) { + filterCount++; + return value % 2 == 0; + }; - var actual = _.map(mapping.aryMethodMap[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]); }); + var map1 = convert('map', _.map), + filter1 = convert('filter', _.filter), + take1 = convert('take', _.take); - if (typeof result != 'function') { - return true; + 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'); + } + else { + skipTest(assert, 3); } - console.log(methodName, result); - return false; }); + }()); - assert.deepEqual(actual, expected); - }); -}()); + /*--------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ + QUnit.module('fp.curry'); -QUnit.module('methods that use `indexOf`'); + (function() { + QUnit.test('should accept only a `func` param', function(assert) { + assert.expect(1); -(function() { - QUnit.test('should work with `fp.indexOf`', function(assert) { - assert.expect(10); + assert.raises(function() { fp.curry(1, _.noop); }, TypeError); + }); + }()); - var array = ['a', 'b', 'c'], - other = ['b', 'b', 'd'], - object = { 'a': 1, 'b': 2, 'c': 2 }, - actual = fp.difference(array, other); + /*--------------------------------------------------------------------------*/ - assert.deepEqual(actual, ['a', 'c'], 'fp.difference'); + QUnit.module('fp.curryN'); - actual = fp.includes('b', array); - assert.strictEqual(actual, true, 'fp.includes'); + (function() { + QUnit.test('should accept an `arity` param', function(assert) { + assert.expect(1); - actual = fp.intersection(other, array); - assert.deepEqual(actual, ['b'], 'fp.intersection'); + var actual = fp.curryN(1, function(a, b) { return [a, b]; })('a'); + assert.deepEqual(actual, ['a', undefined]); + }); + }()); - 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'); + QUnit.module('fp.difference'); - actual = fp.uniq(other); - assert.deepEqual(actual, ['b', 'd'], 'fp.uniq'); + (function() { + QUnit.test('should return the elements of the first array not included in the second array', function(assert) { + assert.expect(1); - actual = fp.uniqBy(_.identity, other); - assert.deepEqual(actual, ['b', 'd'], 'fp.uniqBy'); + assert.deepEqual(fp.difference([1, 2])([2, 3]), [1]); + }); + }()); - actual = fp.without('b', array); - assert.deepEqual(actual, ['a', 'c'], 'fp.without'); + /*--------------------------------------------------------------------------*/ - actual = fp.xor(other, array); - assert.deepEqual(actual, ['a', 'c', 'd'], 'fp.xor'); + QUnit.module('fp.fill'); - actual = fp.pull('b', array); - assert.deepEqual(actual, ['a', 'c'], 'fp.pull'); - }); -}()); + (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.module('cherry-picked methods'); + /*--------------------------------------------------------------------------*/ -(function() { - QUnit.test('should provide the correct `iteratee` arguments', function(assert) { - assert.expect(1); + QUnit.module('fp.flow and fp.flowRight'); - var args, - array = [1, 2, 3], - map = convert('map', _.map); + _.each(['flow', 'flowRight'], function(methodName, index) { + var func = fp[methodName], + isFlow = methodName == 'flow'; - map(function() { - args || (args = slice.call(arguments)); - })(array); + QUnit.test('`fp.' + methodName + '` should support shortcut fusion', function(assert) { + assert.expect(6); - assert.deepEqual(args, [1]); - }); + var filterCount, + mapCount, + array = fp.range(0, LARGE_ARRAY_SIZE); - QUnit.test('should not support shortcut fusion', function(assert) { - assert.expect(3); + var iteratee = function(value) { + mapCount++; + return value * value; + }; - var array = fp.range(0, LARGE_ARRAY_SIZE), - filterCount = 0, - mapCount = 0; + var predicate = function(value) { + filterCount++; + return value % 2 == 0; + }; - var iteratee = function(value) { - mapCount++; - return value * value; - }; + var filter = fp.filter(predicate), + map = fp.map(iteratee), + take = fp.take(2); - var predicate = function(value) { - filterCount++; - return value % 2 == 0; - }; + _.times(2, function(index) { + var combined = isFlow + ? func(map, filter, fp.compact, take) + : func(take, fp.compact, filter, map); - var map1 = convert('map', _.map), - filter1 = convert('filter', _.filter), - take1 = convert('take', _.take); + filterCount = mapCount = 0; - 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('fp.curry'); - -(function() { - QUnit.test('should accept only a `func` param', function(assert) { - assert.expect(1); - - assert.raises(function() { fp.curry(1, _.noop); }, TypeError); - }); -}()); - -/*----------------------------------------------------------------------------*/ - -QUnit.module('fp.curryN'); - -(function() { - QUnit.test('should accept an `arity` param', function(assert) { - assert.expect(1); - - var actual = fp.curryN(1, function(a, b) { return [a, b]; })('a'); - assert.deepEqual(actual, ['a', undefined]); - }); -}()); - -/*----------------------------------------------------------------------------*/ - -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); - - assert.deepEqual(fp.difference([1, 2])([2, 3]), [1]); - }); -}()); - -/*----------------------------------------------------------------------------*/ - -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.module('fp.flow and fp.flowRight'); - -_.each(['flow', 'flowRight'], function(methodName, index) { - 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 value * value; - }; - - var predicate = function(value) { - filterCount++; - return value % 2 == 0; - }; - - 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; - - assert.deepEqual(combined(array), [4, 16]); - assert.strictEqual(filterCount, 5, 'filterCount'); - assert.strictEqual(mapCount, 5, 'mapCount'); + assert.deepEqual(combined(array), [4, 16]); + assert.strictEqual(filterCount, 5, 'filterCount'); + assert.strictEqual(mapCount, 5, 'mapCount'); + }); }); }); -}); -/*----------------------------------------------------------------------------*/ + /*--------------------------------------------------------------------------*/ -QUnit.module('fp.inRange'); + QUnit.module('fp.inRange'); -(function() { - QUnit.test('should have an argument order of `start`, `end`, then `value`', function(assert) { - assert.expect(1); + (function() { + QUnit.test('should have an argument order of `start`, `end`, then `value`', function(assert) { + assert.expect(1); - assert.strictEqual(fp.inRange(2)(4)(3), true); - }); -}()); + assert.strictEqual(fp.inRange(2)(4)(3), true); + }); + }()); -/*----------------------------------------------------------------------------*/ + /*--------------------------------------------------------------------------*/ -QUnit.module('fp.iteratee'); + QUnit.module('fp.iteratee'); -(function() { - QUnit.test('should return a iteratee with capped params', function(assert) { - assert.expect(1); + (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]; }, undefined, 3); - assert.deepEqual(func(1, 2, 3), [1, undefined, undefined]); + var func = fp.iteratee(function(a, b, c) { return [a, b, c]; }, undefined, 3); + assert.deepEqual(func(1, 2, 3), [1, undefined, undefined]); + }); + + QUnit.test('should convert by name', function(assert) { + assert.expect(1); + + if (!document) { + var iteratee = convert('iteratee', _.iteratee), + func = iteratee(function(a, b, c) { return [a, b, c]; }, undefined, 3); + + assert.deepEqual(func(1, 2, 3), [1, undefined, undefined]); + } + else { + skipTest(assert); + } + }); + }()); + + /*--------------------------------------------------------------------------*/ + + QUnit.module('fp.maxBy and fp.minBy'); + + _.each(['maxBy', 'minBy'], function(methodName, index) { + var array = [1, 2, 3], + func = fp[methodName], + isMax = !index; + + 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.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]; }, undefined, 3); + QUnit.module('fp.mixin'); - assert.deepEqual(func(1, 2, 3), [1, undefined, undefined]); - }); -}()); + (function() { + var source = { 'a': _.noop }; -/*----------------------------------------------------------------------------*/ + QUnit.test('should mixin static methods but not prototype methods', function(assert) { + assert.expect(2); -QUnit.module('fp.maxBy and fp.minBy'); + fp.mixin(source); -_.each(['maxBy', 'minBy'], function(methodName, index) { - var array = [1, 2, 3], - func = fp[methodName], - isMax = !index; + assert.strictEqual(typeof fp.a, 'function'); + assert.notOk('a' in fp.prototype); - QUnit.test('`fp.' + methodName + '` should work with an `iteratee` argument', function(assert) { - assert.expect(1); + delete fp.a; + delete fp.prototype.a; + }); - var actual = func(function(num) { - return -num; - })(array); + QUnit.test('should not assign inherited `source` methods', function(assert) { + assert.expect(2); - assert.strictEqual(actual, isMax ? 1 : 3); - }); + function Foo() {} + Foo.prototype.a = _.noop; + fp.mixin(new Foo); - QUnit.test('`fp.' + methodName + '` should provide the correct `iteratee` arguments', function(assert) { - assert.expect(1); + assert.notOk('a' in fp); + assert.notOk('a' in fp.prototype); - var args; + delete fp.a; + delete fp.prototype.a; + }); - func(function() { - args || (args = slice.call(arguments)); - })(array); + QUnit.test('should not remove existing prototype methods', function(assert) { + assert.expect(2); - assert.deepEqual(args, [1]); - }); -}); + var each1 = fp.each, + each2 = fp.prototype.each; -/*----------------------------------------------------------------------------*/ + fp.mixin({ 'each': source.a }); -QUnit.module('fp.mixin'); + assert.strictEqual(fp.each, source.a); + assert.strictEqual(fp.prototype.each, each2); -(function() { - var source = { 'a': _.noop }; + fp.each = each1; + fp.prototype.each = each2; + }); - QUnit.test('should mixin static methods but not prototype methods', function(assert) { - assert.expect(2); + QUnit.test('should not export to the global when `source` is not an object', function(assert) { + assert.expect(2); - fp.mixin(source); + var props = _.without(_.keys(_), '_'); - assert.strictEqual(typeof fp.a, 'function'); - assert.notOk('a' in fp.prototype); + _.times(2, function(index) { + fp.mixin.apply(fp, index ? [1] : []); - delete fp.a; - delete fp.prototype.a; - }); + assert.ok(_.every(props, function(key) { + return root[key] !== fp[key]; + })); - QUnit.test('should not assign inherited `source` methods', function(assert) { - assert.expect(2); + _.each(props, function(key) { + delete root[key]; + }); + }); + }); - function Foo() {} - Foo.prototype.a = _.noop; - fp.mixin(new Foo); + QUnit.test('should convert by name', function(assert) { + assert.expect(3); - assert.notOk('a' in fp); - assert.notOk('a' in fp.prototype); + if (!document) { + var object = { 'mixin': convert('mixin', _.mixin) }; - delete fp.a; - delete fp.prototype.a; - }); + function Foo() {} + Foo.mixin = object.mixin; + Foo.mixin(source); - QUnit.test('should not remove existing prototype methods', function(assert) { - assert.expect(2); + assert.strictEqual(typeof Foo.a, 'function'); + assert.notOk('a' in Foo.prototype); - var each1 = fp.each, - each2 = fp.prototype.each; + object.mixin(source); + assert.strictEqual(typeof object.a, 'function'); + } + else { + skipTest(assert, 3); + } + }); + }()); - fp.mixin({ 'each': source.a }); + /*--------------------------------------------------------------------------*/ - assert.strictEqual(fp.each, source.a); - assert.strictEqual(fp.prototype.each, each2); + QUnit.module('fp.random'); - fp.each = each1; - fp.prototype.each = each2; - }); + (function() { + var array = Array(1000); - QUnit.test('should not export to the global when `source` is not an object', function(assert) { - assert.expect(2); + QUnit.test('should support a `min` and `max` argument', function(assert) { + assert.expect(1); - var props = _.without(_.keys(_), '_'); + var min = 5, + max = 10; - _.times(2, function(index) { - fp.mixin.apply(fp, index ? [1] : []); - - assert.ok(_.every(props, function(key) { - return global[key] !== fp[key]; + assert.ok(_.some(array, function() { + var result = fp.random(min)(max); + return result >= min && result <= max; })); - - _.each(props, function(key) { - delete global[key]; - }); }); - }); + }()); - QUnit.test('should convert by name', function(assert) { - assert.expect(3); + /*--------------------------------------------------------------------------*/ - var object = { 'mixin': convert('mixin', _.mixin) }; + QUnit.module('fp.range'); - function Foo() {} - Foo.mixin = object.mixin; - Foo.mixin(source); + (function() { + QUnit.test('should have an argument order of `start` then `end`', function(assert) { + assert.expect(1); - assert.strictEqual(typeof Foo.a, 'function'); - assert.notOk('a' in Foo.prototype); + assert.deepEqual(fp.range(1)(4), [1, 2, 3]); + }); + }()); - object.mixin(source); - assert.strictEqual(typeof object.a, 'function'); - }); -}()); + /*--------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ + QUnit.module('fp.runInContext'); -QUnit.module('fp.random'); + (function() { + QUnit.test('should return a converted lodash instance', function(assert) { + assert.expect(1); -(function() { - var array = Array(1000); + assert.strictEqual(typeof fp.runInContext({}).curryN, 'function'); + }); - QUnit.test('should support a `min` and `max` argument', function(assert) { - assert.expect(1); + QUnit.test('should convert by name', 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('fp.range'); - -(function() { - QUnit.test('should have an argument order of `start` then `end`', function(assert) { - assert.expect(1); - - assert.deepEqual(fp.range(1)(4), [1, 2, 3]); - }); -}()); - -/*----------------------------------------------------------------------------*/ - -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.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); - - var actual = fp.uniqBy(function(object) { - return object.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.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.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('mutation methods'); - -(function() { - var array = [1, 2, 3], - object = { 'a': 1 }; - - QUnit.test('should not mutate values', function(assert) { - assert.expect(28); - - function Foo() {} - Foo.prototype = { 'b': 2 }; - - var value = _.clone(object), - actual = fp.assign({ 'b': 2 }, value); - - assert.deepEqual(value, object, 'fp.assign'); - assert.deepEqual(actual, { 'a': 1, 'b': 2 }, 'fp.assign'); - - value = _.clone(object); - actual = fp.assignWith(function(objValue, srcValue) { - return srcValue; - }, { 'b': 2 }, value); - - assert.deepEqual(value, object, 'fp.assignWith'); - assert.deepEqual(actual, { 'a': 1, 'b': 2 }, 'fp.assignWith'); - - value = _.clone(object); - actual = fp.defaults({ 'a': 2, 'b': 2 }, value); - - assert.deepEqual(value, object, 'fp.defaults'); - assert.deepEqual(actual, { 'a': 1, 'b': 2 }, 'fp.defaults'); - - value = _.clone(object); - value.b = { 'c': 1 }; - actual = fp.defaultsDeep({ 'b': { 'c': 2, 'd': 2 } }, value); - - assert.deepEqual(value, { 'a': 1, 'b': { 'c': 1 } } , 'fp.defaultsDeep'); - assert.deepEqual(actual, { 'a': 1, 'b': { 'c': 1, 'd': 2 } }, 'fp.defaultsDeep'); - - value = _.clone(object); - actual = fp.extend(new Foo, value); - - assert.deepEqual(value, object, 'fp.extend'); - assert.deepEqual(actual, { 'a': 1, 'b': 2 }, 'fp.extend'); - - value = _.clone(object); - actual = fp.extendWith(function(objValue, srcValue) { - return srcValue; - }, new Foo, value); - - assert.deepEqual(value, object, 'fp.extendWith'); - assert.deepEqual(actual, { 'a': 1, 'b': 2 }, 'fp.extendWith'); - - value = _.clone(array); - actual = fp.fill(1, 2, '*', value); - - assert.deepEqual(value, array, 'fp.fill'); - assert.deepEqual(actual, [1, '*', 3], 'fp.fill'); - - value = { 'a': { 'b': 2 } }; - actual = fp.merge({ 'a': { 'c': 3 } }, value); - - assert.deepEqual(value, { 'a': { 'b': 2 } }, 'fp.merge'); - assert.deepEqual(actual, { 'a': { 'b': 2, 'c': 3 } }, 'fp.merge'); - - value = { 'a': [1] }; - actual = fp.mergeWith(function(objValue, srcValue) { - if (_.isArray(objValue)) { - return objValue.concat(srcValue); + if (!document) { + var runInContext = convert('runInContext', _.runInContext); + assert.strictEqual(typeof runInContext({}).curryN, 'function'); } - }, { 'a': [2, 3] }, value); - - assert.deepEqual(value, { 'a': [1] }, 'fp.mergeWith'); - assert.deepEqual(actual, { 'a': [1, 2, 3] }, 'fp.mergeWith'); - - value = _.clone(array); - actual = fp.pull(2, value); - - assert.deepEqual(value, array, 'fp.pull'); - assert.deepEqual(actual, [1, 3], 'fp.pull'); - - value = _.clone(array); - actual = fp.pullAll([1, 3], value); - - assert.deepEqual(value, array, 'fp.pullAll'); - assert.deepEqual(actual, [2], 'fp.pullAll'); - - value = _.clone(array); - actual = fp.pullAt([0, 2], value); - - assert.deepEqual(value, array, 'fp.pullAt'); - assert.deepEqual(actual, [2], 'fp.pullAt'); - - value = _.clone(array); - actual = fp.remove(function(value) { - return value === 2; - }, value); - - assert.deepEqual(value, array, 'fp.remove'); - assert.deepEqual(actual, [1, 3], 'fp.remove'); - - value = _.clone(array); - actual = fp.reverse(value); - - assert.deepEqual(value, array, 'fp.reverse'); - assert.deepEqual(actual, [3, 2, 1], 'fp.reverse'); - }); -}()); - -/*----------------------------------------------------------------------------*/ - -QUnit.module('with methods'); - -(function() { - var array = [1, 2, 3], - object = { 'a': 1 }; - - QUnit.test('should provice the correct `customizer` arguments', function(assert) { - assert.expect(3); - - var args, - value = _.clone(object); - - var actual = fp.assignWith(function(objValue, srcValue) { - args || (args = _.map(arguments, _.cloneDeep)); - return srcValue; - }, { 'b': 2 }, value); - - assert.deepEqual(args, [undefined, 2, 'b', { 'a': 1 }, { 'b': 2 }], 'fp.assignWith'); - - args = null; - value = _.clone(object); - - actual = fp.extendWith(function(objValue, srcValue) { - args || (args = _.map(arguments, _.cloneDeep)); - return srcValue; - }, { 'b': 2 }, value); - - assert.deepEqual(args, [undefined, 2, 'b', { 'a': 1 }, { 'b': 2 }], 'fp.extendWith'); - - args = null; - value = { 'a': [1] }; - - var stack = { '__data__': { 'array': [], 'map': null } }, - expected = [[1], [2, 3], 'a', { 'a': [ 1 ] }, { 'a': [2, 3] }, stack]; - - actual = fp.mergeWith(function(objValue, srcValue) { - args || (args = _.map(arguments, _.cloneDeep)); - if (_.isArray(objValue)) { - return objValue.concat(srcValue); + else { + skipTest(assert); } - }, { 'a': [2, 3] }, value); + }); + }()); - assert.deepEqual(args, expected, 'fp.mergeWith'); - }); -}()); + /*--------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ + QUnit.module('fp.uniqBy'); -QUnit.config.asyncRetries = 10; -QUnit.config.hidepassed = true; -QUnit.config.noglobals = true; -QUnit.load(); + (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); + + var actual = fp.uniqBy(function(object) { + return object.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.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.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('mutation methods'); + + (function() { + var array = [1, 2, 3], + object = { 'a': 1 }; + + QUnit.test('should not mutate values', function(assert) { + assert.expect(28); + + function Foo() {} + Foo.prototype = { 'b': 2 }; + + var value = _.clone(object), + actual = fp.assign({ 'b': 2 }, value); + + assert.deepEqual(value, object, 'fp.assign'); + assert.deepEqual(actual, { 'a': 1, 'b': 2 }, 'fp.assign'); + + value = _.clone(object); + actual = fp.assignWith(function(objValue, srcValue) { + return srcValue; + }, { 'b': 2 }, value); + + assert.deepEqual(value, object, 'fp.assignWith'); + assert.deepEqual(actual, { 'a': 1, 'b': 2 }, 'fp.assignWith'); + + value = _.clone(object); + actual = fp.defaults({ 'a': 2, 'b': 2 }, value); + + assert.deepEqual(value, object, 'fp.defaults'); + assert.deepEqual(actual, { 'a': 1, 'b': 2 }, 'fp.defaults'); + + value = _.clone(object); + value.b = { 'c': 1 }; + actual = fp.defaultsDeep({ 'b': { 'c': 2, 'd': 2 } }, value); + + assert.deepEqual(value, { 'a': 1, 'b': { 'c': 1 } } , 'fp.defaultsDeep'); + assert.deepEqual(actual, { 'a': 1, 'b': { 'c': 1, 'd': 2 } }, 'fp.defaultsDeep'); + + value = _.clone(object); + actual = fp.extend(new Foo, value); + + assert.deepEqual(value, object, 'fp.extend'); + assert.deepEqual(actual, { 'a': 1, 'b': 2 }, 'fp.extend'); + + value = _.clone(object); + actual = fp.extendWith(function(objValue, srcValue) { + return srcValue; + }, new Foo, value); + + assert.deepEqual(value, object, 'fp.extendWith'); + assert.deepEqual(actual, { 'a': 1, 'b': 2 }, 'fp.extendWith'); + + value = _.clone(array); + actual = fp.fill(1, 2, '*', value); + + assert.deepEqual(value, array, 'fp.fill'); + assert.deepEqual(actual, [1, '*', 3], 'fp.fill'); + + value = { 'a': { 'b': 2 } }; + actual = fp.merge({ 'a': { 'c': 3 } }, value); + + assert.deepEqual(value, { 'a': { 'b': 2 } }, 'fp.merge'); + assert.deepEqual(actual, { 'a': { 'b': 2, 'c': 3 } }, 'fp.merge'); + + value = { 'a': [1] }; + actual = fp.mergeWith(function(objValue, srcValue) { + if (_.isArray(objValue)) { + return objValue.concat(srcValue); + } + }, { 'a': [2, 3] }, value); + + assert.deepEqual(value, { 'a': [1] }, 'fp.mergeWith'); + assert.deepEqual(actual, { 'a': [1, 2, 3] }, 'fp.mergeWith'); + + value = _.clone(array); + actual = fp.pull(2, value); + + assert.deepEqual(value, array, 'fp.pull'); + assert.deepEqual(actual, [1, 3], 'fp.pull'); + + value = _.clone(array); + actual = fp.pullAll([1, 3], value); + + assert.deepEqual(value, array, 'fp.pullAll'); + assert.deepEqual(actual, [2], 'fp.pullAll'); + + value = _.clone(array); + actual = fp.pullAt([0, 2], value); + + assert.deepEqual(value, array, 'fp.pullAt'); + assert.deepEqual(actual, [2], 'fp.pullAt'); + + value = _.clone(array); + actual = fp.remove(function(value) { + return value === 2; + }, value); + + assert.deepEqual(value, array, 'fp.remove'); + assert.deepEqual(actual, [1, 3], 'fp.remove'); + + value = _.clone(array); + actual = fp.reverse(value); + + assert.deepEqual(value, array, 'fp.reverse'); + assert.deepEqual(actual, [3, 2, 1], 'fp.reverse'); + }); + }()); + + /*--------------------------------------------------------------------------*/ + + QUnit.module('with methods'); + + (function() { + var array = [1, 2, 3], + object = { 'a': 1 }; + + QUnit.test('should provice the correct `customizer` arguments', function(assert) { + assert.expect(3); + + var args, + value = _.clone(object); + + var actual = fp.assignWith(function(objValue, srcValue) { + args || (args = _.map(arguments, _.cloneDeep)); + return srcValue; + }, { 'b': 2 }, value); + + assert.deepEqual(args, [undefined, 2, 'b', { 'a': 1 }, { 'b': 2 }], 'fp.assignWith'); + + args = null; + value = _.clone(object); + + actual = fp.extendWith(function(objValue, srcValue) { + args || (args = _.map(arguments, _.cloneDeep)); + return srcValue; + }, { 'b': 2 }, value); + + assert.deepEqual(args, [undefined, 2, 'b', { 'a': 1 }, { 'b': 2 }], 'fp.extendWith'); + + args = null; + value = { 'a': [1] }; + + var stack = { '__data__': { 'array': [], 'map': null } }, + expected = [[1], [2, 3], 'a', { 'a': [ 1 ] }, { 'a': [2, 3] }, stack]; + + actual = fp.mergeWith(function(objValue, srcValue) { + args || (args = _.map(arguments, _.cloneDeep)); + if (_.isArray(objValue)) { + return objValue.concat(srcValue); + } + }, { 'a': [2, 3] }, value); + + assert.deepEqual(args, expected, 'fp.mergeWith'); + }); + }()); + + /*--------------------------------------------------------------------------*/ + + QUnit.config.asyncRetries = 10; + QUnit.config.hidepassed = true; + + if (!document) { + QUnit.config.noglobals = true; + QUnit.load(); + } +}.call(this));