Skip to content
This repository has been archived by the owner on Jul 11, 2023. It is now read-only.

Commit

Permalink
refactor(lodash): replace "defaults" with pure alternative (#692)
Browse files Browse the repository at this point in the history
* refactor(lodash): replace "defaults" with pure alternative

The original lodash tests don't check that it also modifies the target, and as far as I can tell, we don't rely on that behaviour.

* Update src/functions/defaultsPure.js
  • Loading branch information
Haroenv authored and samouss committed May 9, 2019
1 parent 04b21b4 commit b52e519
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 10 deletions.
4 changes: 2 additions & 2 deletions src/SearchParameters/RefinementList.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
var isUndefined = require('lodash/isUndefined');
var isFunction = require('lodash/isFunction');
var isEmpty = require('lodash/isEmpty');
var defaults = require('lodash/defaults');

var defaultsPure = require('../functions/defaultsPure');
var omit = require('../functions/omit');

var lib = {
Expand All @@ -42,7 +42,7 @@ var lib = {

mod[attribute] = facetRefinement;

return defaults({}, mod, refinementList);
return defaultsPure({}, mod, refinementList);
},
/**
* Removes refinement(s) for an attribute:
Expand Down
8 changes: 4 additions & 4 deletions src/SearchParameters/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ var isEqual = require('lodash/isEqual');
var isUndefined = require('lodash/isUndefined');
var isFunction = require('lodash/isFunction');

var defaults = require('lodash/defaults');
var merge = require('lodash/merge');

var defaultsPure = require('../functions/defaultsPure');
var find = require('../functions/find');
var valToNumber = require('../functions/valToNumber');
var omit = require('../functions/omit');
Expand Down Expand Up @@ -1020,7 +1020,7 @@ SearchParameters.prototype = {
}

return this.setQueryParameters({
hierarchicalFacetsRefinements: defaults({}, mod, this.hierarchicalFacetsRefinements)
hierarchicalFacetsRefinements: defaultsPure({}, mod, this.hierarchicalFacetsRefinements)
});
},

Expand All @@ -1038,7 +1038,7 @@ SearchParameters.prototype = {
var mod = {};
mod[facet] = [path];
return this.setQueryParameters({
hierarchicalFacetsRefinements: defaults({}, mod, this.hierarchicalFacetsRefinements)
hierarchicalFacetsRefinements: defaultsPure({}, mod, this.hierarchicalFacetsRefinements)
});
},

Expand All @@ -1055,7 +1055,7 @@ SearchParameters.prototype = {
var mod = {};
mod[facet] = [];
return this.setQueryParameters({
hierarchicalFacetsRefinements: defaults({}, mod, this.hierarchicalFacetsRefinements)
hierarchicalFacetsRefinements: defaultsPure({}, mod, this.hierarchicalFacetsRefinements)
});
},
/**
Expand Down
8 changes: 4 additions & 4 deletions src/SearchResults/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

var orderBy = require('lodash/orderBy');

var defaults = require('lodash/defaults');
var merge = require('lodash/merge');

var isFunction = require('lodash/isFunction');

var partial = require('lodash/partial');
var partialRight = require('lodash/partialRight');

var defaultsPure = require('../functions/defaultsPure');
var compact = require('../functions/compact');
var find = require('../functions/find');
var findIndex = require('../functions/findIndex');
Expand Down Expand Up @@ -462,7 +462,7 @@ function SearchResults(state, results) {

self.disjunctiveFacets[position] = {
name: dfacet,
data: defaults({}, facetResults, dataFromMainRequest),
data: defaultsPure({}, facetResults, dataFromMainRequest),
exhaustive: result.exhaustiveFacetsCount
};
assignFacetStats(self.disjunctiveFacets[position], result.facets_stats, dfacet);
Expand Down Expand Up @@ -526,7 +526,7 @@ function SearchResults(state, results) {
defaultData[root] = self.hierarchicalFacets[position][attributeIndex].data[root];
}

self.hierarchicalFacets[position][attributeIndex].data = defaults(
self.hierarchicalFacets[position][attributeIndex].data = defaultsPure(
defaultData,
facetResults,
self.hierarchicalFacets[position][attributeIndex].data
Expand Down Expand Up @@ -697,7 +697,7 @@ SearchResults.prototype.getFacetValues = function(attribute, opts) {
var facetValues = extractNormalizedFacetValues(this, attribute);
if (!facetValues) throw new Error(attribute + ' is not a retrieved facet.');

var options = defaults({}, opts, {sortBy: SearchResults.DEFAULT_SORT});
var options = defaultsPure({}, opts, {sortBy: SearchResults.DEFAULT_SORT});

if (Array.isArray(options.sortBy)) {
var order = formatSort(options.sortBy, SearchResults.DEFAULT_SORT);
Expand Down
14 changes: 14 additions & 0 deletions src/functions/defaultsPure.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
'use strict';

// NOTE: this behaves like lodash/defaults, but doesn't mutate the target
module.exports = function defaultsPure() {
const sources = Array.prototype.slice.call(arguments);
return sources.reduceRight(function(acc, source) {
Object.keys(Object(source)).forEach(function(key) {
if (source[key] !== undefined) {
acc[key] = source[key];
}
});
return acc;
}, {});
};
66 changes: 66 additions & 0 deletions test/spec/functions/defaultsPure.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
'use strict';

var clone = require('lodash/clone');
var defaults = require('../../../src/functions/defaultsPure');

// tests modified from lodash source

it('should assign source properties if missing on `object`', function() {
var actual = defaults({'a': 1}, {'a': 2, 'b': 2});
expect(actual).toEqual({'a': 1, 'b': 2});
});

it('should accept multiple sources', function() {
var expected = {'a': 1, 'b': 2, 'c': 3};
var actual = defaults({'a': 1, 'b': 2}, {'b': 3}, {'c': 3});

expect(actual).toEqual(expected);

actual = defaults({'a': 1, 'b': 2}, {'b': 3, 'c': 3}, {'c': 2});
expect(actual).toEqual(expected);
});

it('should not overwrite `null` values', function() {
var actual = defaults({'a': null}, {'a': 1});
expect(actual.a).toBe(null);
});

it('should overwrite `undefined` values', function() {
var actual = defaults({'a': undefined}, {'a': 1});
expect(actual.a).toBe(1);
});

it('should assign `undefined` values', function() {
var source = {'a': undefined, 'b': 1};
var actual = defaults({}, source);

expect(actual).toEqual({'a': undefined, 'b': 1});
});

it('should assign properties that shadow those on `Object.prototype`', function() {
var object = {
'constructor': Object.prototype.constructor,
'hasOwnProperty': Object.prototype.hasOwnProperty,
'isPrototypeOf': Object.prototype.isPrototypeOf,
'propertyIsEnumerable': Object.prototype.propertyIsEnumerable,
'toLocaleString': Object.prototype.toLocaleString,
'toString': Object.prototype.toString,
'valueOf': Object.prototype.valueOf
};

var source = {
'constructor': 1,
'hasOwnProperty': 2,
'isPrototypeOf': 3,
'propertyIsEnumerable': 4,
'toLocaleString': 5,
'toString': 6,
'valueOf': 7
};

var expected = clone(source);
expect(defaults({}, source)).toEqual(expected);

expected = clone(object);
expect(defaults({}, object, source)).toEqual(expected);
});

0 comments on commit b52e519

Please sign in to comment.