From 4debf155d70be98cfb1f467e7850f70fed9a91e3 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Fri, 4 Mar 2016 00:55:59 -0800 Subject: [PATCH] Update and add tests for fp convert method. --- fp/_baseConvert.js | 28 ++++++++++--- lib/fp/template/doc/wiki.jst | 66 +++++++++++-------------------- lib/fp/template/modules/_util.jst | 1 + test/test-fp.js | 53 ++++++++++++++++++++----- 4 files changed, 91 insertions(+), 57 deletions(-) diff --git a/fp/_baseConvert.js b/fp/_baseConvert.js index 75973770d..ea336ef2a 100644 --- a/fp/_baseConvert.js +++ b/fp/_baseConvert.js @@ -41,10 +41,12 @@ function baseConvert(util, name, func, options) { }; var forceRearg = ('rearg' in options) && options.rearg, - placeholder = isLib ? func : fallbackHolder; + placeholder = isLib ? func : fallbackHolder, + pristine = isLib ? func.runInContext() : undefined; var helpers = isLib ? func : { 'ary': util.ary, + 'assign': util.assign, 'clone': util.clone, 'curry': util.curry, 'forEach': util.forEach, @@ -58,6 +60,7 @@ function baseConvert(util, name, func, options) { }; var ary = helpers.ary, + assign = helpers.assign, clone = helpers.clone, curry = helpers.curry, each = helpers.forEach, @@ -226,8 +229,19 @@ function baseConvert(util, name, func, options) { var wrap = function(name, func) { name = mapping.aliasToReal[name] || name; var wrapper = wrappers[name]; + + var convert = function(options) { + var newUtil = isLib ? pristine.runInContext() : helpers, + newFunc = isLib ? pristine[name] : func, + newOptions = assign(assign({}, config), options); + + return baseConvert(newUtil, name, newFunc, newOptions); + }; + if (wrapper) { - return wrapper(func); + var result = wrapper(func); + result.convert = convert; + return result; } var wrapped = func; if (config.immutable) { @@ -241,7 +255,6 @@ function baseConvert(util, name, func, options) { wrapped = immutWrap(func, cloneByPath); } } - var result; each(aryMethodKeys, function(aryKey) { each(mapping.aryMethod[aryKey], function(otherName) { if (name == otherName) { @@ -275,13 +288,16 @@ function baseConvert(util, name, func, options) { }); result || (result = wrapped); + if (result == func) { + result = function() { + return func.apply(this, arguments); + }; + } + result.convert = convert; if (mapping.placeholder[name]) { setPlaceholder = true; func.placeholder = result.placeholder = placeholder; } - result.convert = function(options) { - return baseConvert(util, name, func, options); - }; return result; }; diff --git a/lib/fp/template/doc/wiki.jst b/lib/fp/template/doc/wiki.jst index 5e29262c7..7ce2d044b 100644 --- a/lib/fp/template/doc/wiki.jst +++ b/lib/fp/template/doc/wiki.jst @@ -14,7 +14,7 @@ In a browser: In Node.js: ```js // Load the fp build. -var _ = require('lodash/fp'); +var fp = require('lodash/fp'); // Load a method category. var object = require('lodash/fp/object'); @@ -25,27 +25,34 @@ var extend = require('lodash/fp/extend'); ## Convert -Although `lodash/fp` & its method modules come pre-converted, there are times when -you may want to customize the conversion. That’s when the `convert` method comes in handy. - - +Although `lodash/fp` & its method modules come pre-converted, there are times +when you may want to customize the conversion. That’s when the `convert` method +comes in handy. ```js -// Disable capping of the iteratee arguments so it is possible to access -// the `key` argument -var mapValuesWithKey = require("lodash/fp/mapValues").convert({cap: false}); +// Every option is `true` by default. +var mapValues = fp.mapValues.convert({ + // Specify capping iteratee arguments. + 'cap': true, + // Specify currying. + 'curry': true, + // Specify fixed arity. + 'fixed': true, + // Specify immutable operations. + 'immutable': true, + // Specify rearranging arguments. + 'rearg': true +}); + +// Disable capping of iteratee arguments to access the `key` param. +var mapValuesWithKey = fp.mapValues.convert({ 'cap': false }); mapValuesWithKey(function(value, key) { - if (key === "foo") { - return -1; - } - return value; -}, {foo: 1, bar: 1}); -// => {foo: -1, bar: 1} + return key == 'a' ? -1 : value; +})({ 'a': 1, 'b': 1 }); +// => { 'a': -1, 'b': 1 } ``` -It's also possible to use the convert function directly to convert functions or -objects manually. - +It’s also possible to use the convert module directly for manual conversions. ```js var convert = require('lodash/fp/convert'); @@ -62,31 +69,6 @@ var fp = convert({ var fp = convert(lodash.runInContext()); ``` -It’s customizable too. -```js -// Every option is `true` by default. -var filter = convert('filter', _.filter, { - // Specify capping iteratee arguments. - 'cap': true, - // Specify currying. - 'curry': true, - // Specify fixed arity. - 'fixed': true, - // Specify immutable operations. - 'immutable': true, - // Specify rearranging arguments. - 'rearg': true -}); - -// Specify `cap` of `false` to create a function that doesn’t cap iteratee arguments. -var filter = convert('filter', _.filter, { 'cap': false }); - -filter(function(value, index) { - return index % 2 == 0; -})(['a', 'b', 'c']); -// => ['a', 'c'] -``` - ## Mapping Immutable auto-curried iteratee-first data-last methods sound great, but what diff --git a/lib/fp/template/modules/_util.jst b/lib/fp/template/modules/_util.jst index afa811bc6..d450396fc 100644 --- a/lib/fp/template/modules/_util.jst +++ b/lib/fp/template/modules/_util.jst @@ -1,5 +1,6 @@ module.exports = { 'ary': require('../ary'), + 'assign': require('../_baseAssign'), 'clone': require('../clone'), 'curry': require('../curry'), 'forEach': require('../_arrayEach'), diff --git a/test/test-fp.js b/test/test-fp.js index c69d9486d..7f4ffaf4a 100644 --- a/test/test-fp.js +++ b/test/test-fp.js @@ -67,6 +67,14 @@ }; }()); + var allFalseOptions = { + 'cap': false, + 'curry': false, + 'fixed': false, + 'immutable': false, + 'rearg': false + }; + var fp = root.fp ? (fp = _.noConflict(), _ = root._, fp) : convert(_.runInContext()); @@ -95,17 +103,9 @@ console.log('Running lodash/fp tests.'); } - QUnit.module('convert'); + QUnit.module('convert module'); (function() { - var allFalseOptions = { - 'cap': false, - 'curry': false, - 'fixed': false, - 'immutable': false, - 'rearg': false - }; - QUnit.test('should work when given an object', function(assert) { assert.expect(2); @@ -274,6 +274,41 @@ /*--------------------------------------------------------------------------*/ + QUnit.module('convert method'); + + (function() { + QUnit.test('should work when given an object', function(assert) { + assert.expect(3); + + var array = [1, 2, 3, 4], + remove = fp.remove.convert(allFalseOptions); + + var actual = remove(array, function(n, index) { + return index % 2 == 0; + }); + + assert.deepEqual(array, [2, 4]); + assert.deepEqual(actual, [1, 3]); + assert.deepEqual(remove(), []); + }); + + QUnit.test('should extend existing configs', function(assert) { + assert.expect(2); + + var array = [1, 2, 3, 4], + remove = fp.remove.convert({ 'cap': false }).convert({ 'rearg': false }); + + var actual = remove(array)(function(n, index) { + return index % 2 == 0; + }); + + assert.deepEqual(array, [1, 2, 3, 4]); + assert.deepEqual(actual, [2, 4]); + }); + }()); + + /*--------------------------------------------------------------------------*/ + QUnit.module('method arity checks'); (function() {