diff --git a/lib/common/utils.js b/lib/common/utils.js index 24a08f454a..8fe5f4e193 100644 --- a/lib/common/utils.js +++ b/lib/common/utils.js @@ -72,20 +72,22 @@ export function chainFn (base, fn) { if (!(fn instanceof Function)) { return } - if (typeof base !== 'function') { - return fn.apply(this, arguments) + return function () { + if (typeof base !== 'function') { + return fn.apply(this, arguments) + } + let baseResult = base.apply(this, arguments) + // Allow function to mutate the first argument instead of returning the result + if (baseResult === undefined) { + baseResult = arguments[0] + } + let fnResult = fn.call(this, baseResult, ...Array.prototype.slice.call(arguments, 1)) + // Return mutated argument if no result was returned + if (fnResult === undefined) { + return baseResult + } + return fnResult } - let baseResult = base.apply(this, arguments) - // Allow function to mutate the first argument instead of returning the result - if (baseResult === undefined) { - baseResult = arguments[0] - } - let fnResult = fn.call(this, baseResult, ...arguments.slice(1)) - // Return mutated argument if no result was returned - if (fnResult === undefined) { - return baseResult - } - return fnResult } export function isPureObject (o) { diff --git a/test/utils.test.js b/test/utils.test.js index de741554ac..e96253bb6a 100644 --- a/test/utils.test.js +++ b/test/utils.test.js @@ -94,3 +94,52 @@ test('promisifyRoute (fn(cb) with result)', t => { t.is(res, array) }) }) + +test('chainFn (mutate, mutate)', t => { + // Pass more than one argument to test that they're actually taken into account + const firstFn = function (obj, count) { + obj.foo = count + 1 + } + const secondFn = function (obj, count) { + obj.bar = count + 2 + } + const chainedFn = Utils.chainFn(firstFn, secondFn) + const expectedResult = { foo: 11, bar: 12 } + t.deepEqual(chainedFn({}, 10), expectedResult) +}) + +test('chainFn (mutate, return)', t => { + const firstFn = function (obj, count) { + obj.foo = count + 1 + } + const secondFn = function (obj, count) { + return Object.assign({}, obj, { bar: count + 2 }) + } + const chainedFn = Utils.chainFn(firstFn, secondFn) + const expectedResult = { foo: 11, bar: 12 } + t.deepEqual(chainedFn({}, 10), expectedResult) +}) + +test('chainFn (return, mutate)', t => { + const firstFn = function (obj, count) { + return Object.assign({}, obj, { foo: count + 1 }) + } + const secondFn = function (obj, count) { + obj.bar = count + 2 + } + const chainedFn = Utils.chainFn(firstFn, secondFn) + const expectedResult = { foo: 11, bar: 12 } + t.deepEqual(chainedFn({}, 10), expectedResult) +}) + +test('chainFn (return, return)', t => { + const firstFn = function (obj, count) { + return Object.assign({}, obj, { foo: count + 1 }) + } + const secondFn = function (obj, count) { + return Object.assign({}, obj, { bar: count + 2 }) + } + const chainedFn = Utils.chainFn(firstFn, secondFn) + const expectedResult = { foo: 11, bar: 12 } + t.deepEqual(chainedFn({}, 10), expectedResult) +})