Comparing version 2.5.0 to 2.6.0
@@ -134,5 +134,34 @@ # ObjectUtils | ||
### `formatKeys` | ||
Formats all the keys on an object using a way similar to `.replace(regexp, ...)` but that also works recursively and with _"object paths"_. | ||
```js | ||
const target = { | ||
prop_one: 'Charito!', | ||
}; | ||
console.log(ObjectUtils.formatKeys( | ||
target, | ||
// Find all the keys with snake case. | ||
/([a-z])_([a-z])/g, | ||
// Using the same .replace style callback, replace it with lower camel case. | ||
(fullMatch, firstLetter, secondLetter) => { | ||
const newSecondLetter = secondLetter.toUpperCase(); | ||
return `${firstLetter}${newSecondLetter}`; | ||
} | ||
)); | ||
``` | ||
`ObjectUtils` also provides a few "shorthand implementations" of `formatKeys`: | ||
- `lowerCamelToSnakeKeys(...)` | ||
- `lowerCamelToDashKeys(...)` | ||
- `snakeToLowerCamelKeys(...)` | ||
- `snakeToDashKeys(...)` | ||
- `dashToLowerCamelKeys(...)` | ||
- `dashToSnakeKeys(...)` | ||
## Technical documentation | ||
The code is fully documented with [ESDoc](https://esdoc.org) and you can either read the generated documentation [online](https://homer0.github.io/wootils/class/wootils/shared/eventsHub.js~EventsHub.html) or generate it yourself using: | ||
The code is fully documented with [ESDoc](https://esdoc.org) and you can either read the generated documentation [online](https://homer0.github.io/wootils/class/wootils/shared/objectUtils.js~ObjectUtils.html) or generate it yourself using: | ||
@@ -139,0 +168,0 @@ ```bash |
@@ -5,3 +5,3 @@ { | ||
"homepage": "https://homer0.github.io/wootils/", | ||
"version": "2.5.0", | ||
"version": "2.6.0", | ||
"repository": "homer0/wootils", | ||
@@ -21,7 +21,7 @@ "author": "Leonardo Apiwan (@homer0) <me@homer0.com>", | ||
"eslint-config-airbnb-base": "^13.2.0", | ||
"eslint-plugin-import": "^2.18.0", | ||
"eslint-plugin-import": "^2.18.2", | ||
"eslint-plugin-node": "^9.1.0", | ||
"jest-ex": "^6.1.1", | ||
"jest-cli": "^24.8.0", | ||
"jasmine-expect": "^4.0.2", | ||
"jasmine-expect": "^4.0.3", | ||
"@babel/preset-env": "7.5.5", | ||
@@ -33,3 +33,3 @@ "@babel/core": "7.5.5", | ||
"esdoc-node": "^1.0.4", | ||
"leasot": "^7.5.0", | ||
"leasot": "^8.0.0", | ||
"coveralls": "^3.0.5" | ||
@@ -36,0 +36,0 @@ }, |
@@ -363,4 +363,383 @@ const extend = require('extend'); | ||
} | ||
/** | ||
* Formats all the keys on an object using a way similar to `.replace(regexp, ...)` but that | ||
* also works recursively and with _"object paths"_. | ||
* @example | ||
* const target = { | ||
* prop_one: 'Charito!', | ||
* }; | ||
* console.log(ObjectUtils.formatKeys( | ||
* target, | ||
* // Find all the keys with snake case. | ||
* /([a-z])_([a-z])/g, | ||
* // Using the same .replace style callback, replace it with lower camel case. | ||
* (fullMatch, firstLetter, secondLetter) => { | ||
* const newSecondLetter = secondLetter.toUpperCase(); | ||
* return `${firstLetter}${newSecondLetter}`; | ||
* } | ||
* )); | ||
* // Will output { propOne: 'Charito!}. | ||
* | ||
* @param {Object} target The object for format. | ||
* @param {RegExp} searchExpression The regular expression the method will use "match" the | ||
* keys. | ||
* @param {Function} replaceWith The callback the method will call when formatting a | ||
* replace. Think of `searchExpression` and `replaceWith` | ||
* as the parameters of a `.replace` call, where the | ||
* object is the key. | ||
* @param {Array} [include=[]] A list of keys or paths where the transformation will | ||
* be made. If not specified, the method will use all the | ||
* keys from the object. | ||
* @param {Array} [exclude=[]] A list of keys or paths where the transformation won't | ||
* be made. | ||
* @param {string} [pathDelimiter='.'] The delimiter that will separate the path components | ||
* for both `include` and `exclude`. | ||
* @return {Object} | ||
*/ | ||
static formatKeys( | ||
target, | ||
searchExpression, | ||
replaceWith, | ||
include = [], | ||
exclude = [], | ||
pathDelimiter = '.' | ||
) { | ||
// First of all, get all the keys from the target. | ||
const keys = Object.keys(target); | ||
/** | ||
* Then, check which keys are parent to other objects. | ||
* This is saved on a dictionary not only because it makes it easier to check if the method | ||
* should make a recursive call for a key, but also because when parsing the `exclude` | ||
* parameter, if one of items is a key (and not an specific path), the method won't make the | ||
* recursive call. | ||
*/ | ||
const hasChildrenByKey = {}; | ||
keys.forEach((key) => { | ||
const value = target[key]; | ||
hasChildrenByKey[key] = !!( | ||
typeof value === 'object' && | ||
!Array.isArray(value) && | ||
Object.keys(value) | ||
); | ||
}); | ||
/** | ||
* Escape the path delimiter and create two regular expression: One that removes the path | ||
* delimiter from the start of a path and one that removes it from the end. | ||
* They are later used to normalize paths in order to avoid "incomplete paths" (paths that | ||
* end or start with the delimiter). | ||
*/ | ||
const escapedPathDelimiter = pathDelimiter.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); | ||
const cleanPathStartExpression = new RegExp(`^${escapedPathDelimiter}`, 'i'); | ||
const cleanPathEndExpression = new RegExp(`${escapedPathDelimiter}$`, 'i'); | ||
/** | ||
* This dictionary will be used to save the `include` parameter that will be sent for specific | ||
* keys on recursive calls. | ||
* If `include` has a path like `myKey.mySubKey`, `myKey` is not transformed, but `mySubKey` | ||
* is saved on this dictionary (`{ myKey: ['mySubKey']}`) and when the method applies the | ||
* formatting to the object, if `myKey` has an object, it will make a recursive all and | ||
* send `['mySubKey]` as its `include` parameter. | ||
*/ | ||
const subIncludeByKey = {}; | ||
/** | ||
* This will be an array containing the final list of `keys` that should be tranformed. | ||
* To be clear, these keys will be from the top level, so, they won't be paths. | ||
* Thd following blocks will parse `include` and `exclude` in order to extract the real keys, | ||
* prepare the `include` and `exclude` for recursive calls, and save the actual keys | ||
* from the object "at the current level of this call" (no, it's not thinking about the | ||
* children :P). | ||
*/ | ||
let keysToFormat; | ||
// If the `include` parameter has paths/keys... | ||
if (include.length) { | ||
keysToFormat = include | ||
.map((includePath) => { | ||
// Normalize the path/key. | ||
const useIncludePath = includePath | ||
.replace(cleanPathStartExpression, '') | ||
.replace(cleanPathEndExpression, ''); | ||
// Define the variable that will, eventually, have the real key. | ||
let key; | ||
// If the value is a path... | ||
if (useIncludePath.includes(pathDelimiter)) { | ||
// Split all its components. | ||
const pathParts = useIncludePath.split(pathDelimiter); | ||
// Get the first component, a.k.a. the real key. | ||
const pathKey = pathParts.shift(); | ||
/** | ||
* This is very important: Since the path was specified with sub components (like | ||
* `myProp.mySubProp`), the method won't format the key, but the sub key(s) | ||
* (`mySubProp`). | ||
* The `key` is set to `false` so it will be later removed using `.filter`. | ||
*/ | ||
key = false; | ||
/** | ||
* If there's no array for the key on the "`include` dictionary for recursive calls", | ||
* create an empty one. | ||
*/ | ||
if (!subIncludeByKey[pathKey]) { | ||
subIncludeByKey[pathKey] = []; | ||
} | ||
// Save the rest of the path to be sent on the recursive call as `include`. | ||
subIncludeByKey[pathKey].push(pathParts.join(pathDelimiter)); | ||
} else { | ||
// If the value wasn't a path, assume it's a key, and set it to be returned. | ||
key = useIncludePath; | ||
} | ||
return key; | ||
}) | ||
// Remove any `false` keys. | ||
.filter((key) => key); | ||
} else { | ||
// There's nothing on the `include` parameter, so use all the keys. | ||
keysToFormat = keys; | ||
} | ||
/** | ||
* Similar to `subIncludeByKey`, this dictionary will be used to save the `exclude` parameter | ||
* that will be sent for specific keys on recursive calls. | ||
* If `exclude` has a path like `myKey.mySubKey`, `myKey` will be transformed, but `mySubKey` | ||
* is saved on this dictionary (`{ myKey: ['mySubKey']}`) and when the method applies the | ||
* formatting to the object, if `myKey` has an object, it will make a recursive all and | ||
* send `['mySubKey]` as its `exclude` parameter. | ||
*/ | ||
const subExcludeByKey = {}; | ||
// If the `include` parameter has paths/keys... | ||
if (exclude.length) { | ||
/** | ||
* Create a dictionary of keys that should be removed from `keysToFormat`. | ||
* It's easier to have them on a list and use `.filter` than actually call `.splice` for | ||
* every key that should be removed. | ||
*/ | ||
const keysToRemove = []; | ||
exclude.forEach((excludePath) => { | ||
// Normalize the path/key. | ||
const useExcludePath = excludePath | ||
.replace(cleanPathStartExpression, '') | ||
.replace(cleanPathEndExpression, ''); | ||
// If the value is a path... | ||
if (useExcludePath.includes(pathDelimiter)) { | ||
// Split all its components. | ||
const pathParts = useExcludePath.split(pathDelimiter); | ||
// Get the first component, a.k.a. the real key. | ||
const pathKey = pathParts.shift(); | ||
/** | ||
* If there's no array for the key on the "`exclude` dictionary for recursive calls", | ||
* create an empty one. | ||
*/ | ||
if (!subExcludeByKey[pathKey]) { | ||
subExcludeByKey[pathKey] = []; | ||
} | ||
// Save the rest of the path to be sent on the recursive call as `exclude`. | ||
subExcludeByKey[pathKey].push(pathParts.join(pathDelimiter)); | ||
} else { | ||
/** | ||
* If the value wasn't a path, assume it's a key, turn the flag on the "children | ||
* dictionary" to `false`, to prevent recursive calls, and add the key to the list | ||
* of keys that will be removed from `keysToFormat`. | ||
* Basically: If it's a key, don't format it and don't make recursive calls for it. | ||
*/ | ||
hasChildrenByKey[useExcludePath] = false; | ||
keysToRemove.push(useExcludePath); | ||
} | ||
}); | ||
// Remove keys that should be excluded. | ||
keysToFormat = keysToFormat.filter((key) => !keysToRemove.includes(key)); | ||
} | ||
// "Finally", reduce all the keys from the object and create the new one... | ||
return keys.reduce( | ||
(newObj, key) => { | ||
/** | ||
* Define the new key and value for the object property. Depending on the validations, | ||
* they may be replaced with formatted ones. | ||
*/ | ||
let newKey; | ||
let newValue; | ||
/** | ||
* Get the current value for the key, in case it's needed for a recursive call or just | ||
* to send it back because it didn't need any change. | ||
*/ | ||
const value = target[key]; | ||
// If the key should be formatted, apply the formatting; otherwise, keep the original. | ||
if (keysToFormat.includes(key)) { | ||
newKey = key.replace(searchExpression, replaceWith); | ||
} else { | ||
newKey = key; | ||
} | ||
/** | ||
* If the paths/keys on `exclude` didn't modify the "children dictionary" for the key and | ||
* the value is another object, make a recursive call; otherwise, just use the original | ||
* value. | ||
*/ | ||
if (hasChildrenByKey[key]) { | ||
newValue = this.formatKeys( | ||
value, | ||
searchExpression, | ||
replaceWith, | ||
subIncludeByKey[key] || [], | ||
subExcludeByKey[key] || [], | ||
pathDelimiter | ||
); | ||
} else { | ||
newValue = value; | ||
} | ||
// "Done", return the new object with the "new key" and the "new value". | ||
return Object.assign({}, newObj, { | ||
[newKey]: newValue, | ||
}); | ||
}, | ||
{} | ||
); | ||
} | ||
/** | ||
* A shorthand method for {@link ObjectUtils.formatKeys} that transforms the keys from | ||
* `lowerCamelCase` to `snake_case`. | ||
* @param {Object} target The object for format. | ||
* @param {Array} [include=[]] A list of keys or paths where the transformation will | ||
* be made. If not specified, the method will use all the | ||
* keys from the object. | ||
* @param {Array} [exclude=[]] A list of keys or paths where the transformation won't | ||
* be made. | ||
* @param {string} [pathDelimiter='.'] The delimiter that will separate the path components | ||
* for both `include` and `exclude`. | ||
* @return {Object} | ||
*/ | ||
static lowerCamelToSnakeKeys(target, include = [], exclude = [], pathDelimiter = '.') { | ||
return this.formatKeys( | ||
target, | ||
/([a-z])([A-Z])/g, | ||
(fullMatch, firstLetter, secondLetter) => { | ||
const newSecondLetter = secondLetter.toLowerCase(); | ||
return `${firstLetter}_${newSecondLetter}`; | ||
}, | ||
include, | ||
exclude, | ||
pathDelimiter | ||
); | ||
} | ||
/** | ||
* A shorthand method for {@link ObjectUtils.formatKeys} that transforms the keys from | ||
* `lowerCamelCase` to `dash-case`. | ||
* @param {Object} target The object for format. | ||
* @param {Array} [include=[]] A list of keys or paths where the transformation will | ||
* be made. If not specified, the method will use all the | ||
* keys from the object. | ||
* @param {Array} [exclude=[]] A list of keys or paths where the transformation won't | ||
* be made. | ||
* @param {string} [pathDelimiter='.'] The delimiter that will separate the path components | ||
* for both `include` and `exclude`. | ||
* @return {Object} | ||
*/ | ||
static lowerCamelToDashKeys(target, include = [], exclude = [], pathDelimiter = '.') { | ||
return this.formatKeys( | ||
target, | ||
/([a-z])([A-Z])/g, | ||
(fullMatch, firstLetter, secondLetter) => { | ||
const newSecondLetter = secondLetter.toLowerCase(); | ||
return `${firstLetter}-${newSecondLetter}`; | ||
}, | ||
include, | ||
exclude, | ||
pathDelimiter | ||
); | ||
} | ||
/** | ||
* A shorthand method for {@link ObjectUtils.formatKeys} that transforms the keys from | ||
* `snake_case` to `lowerCamelCase`. | ||
* @param {Object} target The object for format. | ||
* @param {Array} [include=[]] A list of keys or paths where the transformation will | ||
* be made. If not specified, the method will use all the | ||
* keys from the object. | ||
* @param {Array} [exclude=[]] A list of keys or paths where the transformation won't | ||
* be made. | ||
* @param {string} [pathDelimiter='.'] The delimiter that will separate the path components | ||
* for both `include` and `exclude`. | ||
* @return {Object} | ||
*/ | ||
static snakeToLowerCamelKeys(target, include = [], exclude = [], pathDelimiter = '.') { | ||
return this.formatKeys( | ||
target, | ||
/([a-z])_([a-z])/g, | ||
(fullMatch, firstLetter, secondLetter) => { | ||
const newSecondLetter = secondLetter.toUpperCase(); | ||
return `${firstLetter}${newSecondLetter}`; | ||
}, | ||
include, | ||
exclude, | ||
pathDelimiter | ||
); | ||
} | ||
/** | ||
* A shorthand method for {@link ObjectUtils.formatKeys} that transforms the keys from | ||
* `snake_case` to `dash-case`. | ||
* @param {Object} target The object for format. | ||
* @param {Array} [include=[]] A list of keys or paths where the transformation will | ||
* be made. If not specified, the method will use all the | ||
* keys from the object. | ||
* @param {Array} [exclude=[]] A list of keys or paths where the transformation won't | ||
* be made. | ||
* @param {string} [pathDelimiter='.'] The delimiter that will separate the path components | ||
* for both `include` and `exclude`. | ||
* @return {Object} | ||
*/ | ||
static snakeToDashKeys(target, include = [], exclude = [], pathDelimiter = '.') { | ||
return this.formatKeys( | ||
target, | ||
/([a-z])_([a-z])/g, | ||
(fullMatch, firstLetter, secondLetter) => `${firstLetter}-${secondLetter}`, | ||
include, | ||
exclude, | ||
pathDelimiter | ||
); | ||
} | ||
/** | ||
* A shorthand method for {@link ObjectUtils.formatKeys} that transforms the keys from | ||
* `dash-case` to `lowerCamelCase`. | ||
* @param {Object} target The object for format. | ||
* @param {Array} [include=[]] A list of keys or paths where the transformation will | ||
* be made. If not specified, the method will use all the | ||
* keys from the object. | ||
* @param {Array} [exclude=[]] A list of keys or paths where the transformation won't | ||
* be made. | ||
* @param {string} [pathDelimiter='.'] The delimiter that will separate the path components | ||
* for both `include` and `exclude`. | ||
* @return {Object} | ||
*/ | ||
static dashToLowerCamelKeys(target, include = [], exclude = [], pathDelimiter = '.') { | ||
return this.formatKeys( | ||
target, | ||
/([a-z])-([a-z])/g, | ||
(fullMatch, firstLetter, secondLetter) => { | ||
const newSecondLetter = secondLetter.toUpperCase(); | ||
return `${firstLetter}${newSecondLetter}`; | ||
}, | ||
include, | ||
exclude, | ||
pathDelimiter | ||
); | ||
} | ||
/** | ||
* A shorthand method for {@link ObjectUtils.formatKeys} that transforms the keys from | ||
* `dash-case` to `snake_case`. | ||
* @param {Object} target The object for format. | ||
* @param {Array} [include=[]] A list of keys or paths where the transformation will | ||
* be made. If not specified, the method will use all the | ||
* keys from the object. | ||
* @param {Array} [exclude=[]] A list of keys or paths where the transformation won't | ||
* be made. | ||
* @param {string} [pathDelimiter='.'] The delimiter that will separate the path components | ||
* for both `include` and `exclude`. | ||
* @return {Object} | ||
*/ | ||
static dashToSnakeKeys(target, include = [], exclude = [], pathDelimiter = '.') { | ||
return this.formatKeys( | ||
target, | ||
/([a-z])-([a-z])/g, | ||
(fullMatch, firstLetter, secondLetter) => `${firstLetter}_${secondLetter}`, | ||
include, | ||
exclude, | ||
pathDelimiter | ||
); | ||
} | ||
} | ||
module.exports = ObjectUtils; |
@@ -747,2 +747,547 @@ jest.unmock('/shared/objectUtils'); | ||
}); | ||
describe('formatKeys', () => { | ||
it('should make all keys first letters into upper case', () => { | ||
// Given | ||
const name = 'Rosario'; | ||
const nickname = 'Charito'; | ||
const age = 3; | ||
const target = { | ||
name, | ||
nickname, | ||
age, | ||
}; | ||
let result = null; | ||
// When | ||
result = ObjectUtils.formatKeys( | ||
target, | ||
/^\w/, | ||
(letter) => letter.toUpperCase() | ||
); | ||
// Then | ||
expect(result).toEqual({ | ||
Name: name, | ||
Nickname: nickname, | ||
Age: age, | ||
}); | ||
}); | ||
it('should make specific keys first letters into upper case', () => { | ||
// Given | ||
const first = 'Rosario'; | ||
const nickname = 'Charito'; | ||
const age = 3; | ||
const likes = 'ice-cream'; | ||
const target = { | ||
name: { | ||
first, | ||
nickname, | ||
}, | ||
age, | ||
likes, | ||
}; | ||
let result = null; | ||
// When | ||
result = ObjectUtils.formatKeys( | ||
target, | ||
/^\w/, | ||
(letter) => letter.toUpperCase(), | ||
['name.first', 'likes'] | ||
); | ||
// Then | ||
expect(result).toEqual({ | ||
name: { | ||
First: first, | ||
nickname, | ||
}, | ||
age, | ||
Likes: likes, | ||
}); | ||
}); | ||
it('should make specific keys first letters into upper case (incomplete paths)', () => { | ||
// Given | ||
const first = 'Rosario'; | ||
const nickname = 'Charito'; | ||
const age = 3; | ||
const likes = 'ice-cream'; | ||
const target = { | ||
name: { | ||
first, | ||
nickname, | ||
}, | ||
age, | ||
likes, | ||
}; | ||
let result = null; | ||
// When | ||
result = ObjectUtils.formatKeys( | ||
target, | ||
/^\w/, | ||
(letter) => letter.toUpperCase(), | ||
['name.first.', '.name.nickname.', 'likes'] | ||
); | ||
// Then | ||
expect(result).toEqual({ | ||
name: { | ||
First: first, | ||
Nickname: nickname, | ||
}, | ||
age, | ||
Likes: likes, | ||
}); | ||
}); | ||
it('should exclude some keys when transforming them', () => { | ||
// Given | ||
const first = 'Rosario'; | ||
const nickname = 'Charito'; | ||
const age = 3; | ||
const likes = 'ice-cream'; | ||
const target = { | ||
name: { | ||
first, | ||
nickname, | ||
}, | ||
age, | ||
likes, | ||
}; | ||
let result = null; | ||
// When | ||
result = ObjectUtils.formatKeys( | ||
target, | ||
/^\w/, | ||
(letter) => letter.toUpperCase(), | ||
[], | ||
['name.first', 'likes'] | ||
); | ||
// Then | ||
expect(result).toEqual({ | ||
Name: { | ||
first, | ||
Nickname: nickname, | ||
}, | ||
Age: age, | ||
likes, | ||
}); | ||
}); | ||
it('should exclude some keys when transforming them (incomplete paths)', () => { | ||
// Given | ||
const first = 'Rosario'; | ||
const nickname = 'Charito'; | ||
const age = 3; | ||
const likes = 'ice-cream'; | ||
const target = { | ||
name: { | ||
first, | ||
nickname, | ||
}, | ||
age, | ||
likes, | ||
}; | ||
let result = null; | ||
// When | ||
result = ObjectUtils.formatKeys( | ||
target, | ||
/^\w/, | ||
(letter) => letter.toUpperCase(), | ||
[], | ||
['name.first.', '.name.nickname.', '.likes'] | ||
); | ||
// Then | ||
expect(result).toEqual({ | ||
Name: { | ||
first, | ||
nickname, | ||
}, | ||
Age: age, | ||
likes, | ||
}); | ||
}); | ||
}); | ||
describe('lowerCamelToSnakeKeys', () => { | ||
it('should transform all keys to snake case', () => { | ||
// Given | ||
const firstName = 'Rosario'; | ||
const nickName = 'Charito'; | ||
const target = { | ||
firstName, | ||
nickName, | ||
}; | ||
let result = null; | ||
// When | ||
result = ObjectUtils.lowerCamelToSnakeKeys(target); | ||
// Then | ||
expect(result).toEqual({ | ||
first_name: firstName, | ||
nick_name: nickName, | ||
}); | ||
}); | ||
it('should transform specific keys to snake case', () => { | ||
// Given | ||
const firstName = 'Rosario'; | ||
const nickName = 'Charito'; | ||
const target = { | ||
name: { | ||
firstName, | ||
nickName, | ||
}, | ||
}; | ||
let result = null; | ||
// When | ||
result = ObjectUtils.lowerCamelToSnakeKeys(target, ['name.firstName']); | ||
// Then | ||
expect(result).toEqual({ | ||
name: { | ||
first_name: firstName, | ||
nickName, | ||
}, | ||
}); | ||
}); | ||
it('should transform all keys to snake case except one', () => { | ||
// Given | ||
const firstName = 'Rosario'; | ||
const nickName = 'Charito'; | ||
const target = { | ||
nameInfo: { | ||
firstName, | ||
nickName, | ||
}, | ||
}; | ||
let result = null; | ||
// When | ||
result = ObjectUtils.lowerCamelToSnakeKeys(target, [], ['nameInfo.firstName']); | ||
// Then | ||
expect(result).toEqual({ | ||
name_info: { | ||
firstName, | ||
nick_name: nickName, | ||
}, | ||
}); | ||
}); | ||
}); | ||
describe('lowerCamelToDashKeys', () => { | ||
it('should transform all keys to dash case', () => { | ||
// Given | ||
const firstName = 'Rosario'; | ||
const nickName = 'Charito'; | ||
const target = { | ||
firstName, | ||
nickName, | ||
}; | ||
let result = null; | ||
// When | ||
result = ObjectUtils.lowerCamelToDashKeys(target); | ||
// Then | ||
expect(result).toEqual({ | ||
'first-name': firstName, | ||
'nick-name': nickName, | ||
}); | ||
}); | ||
it('should transform specific keys to dash case', () => { | ||
// Given | ||
const firstName = 'Rosario'; | ||
const nickName = 'Charito'; | ||
const target = { | ||
name: { | ||
firstName, | ||
nickName, | ||
}, | ||
}; | ||
let result = null; | ||
// When | ||
result = ObjectUtils.lowerCamelToDashKeys(target, ['name.firstName']); | ||
// Then | ||
expect(result).toEqual({ | ||
name: { | ||
'first-name': firstName, | ||
nickName, | ||
}, | ||
}); | ||
}); | ||
it('should transform all keys to dash case except one', () => { | ||
// Given | ||
const firstName = 'Rosario'; | ||
const nickName = 'Charito'; | ||
const target = { | ||
nameInfo: { | ||
firstName, | ||
nickName, | ||
}, | ||
}; | ||
let result = null; | ||
// When | ||
result = ObjectUtils.lowerCamelToDashKeys(target, [], ['nameInfo.firstName']); | ||
// Then | ||
expect(result).toEqual({ | ||
'name-info': { | ||
firstName, | ||
'nick-name': nickName, | ||
}, | ||
}); | ||
}); | ||
}); | ||
describe('snakeToLowerCamelKeys', () => { | ||
it('should transform all keys to lower camel case', () => { | ||
// Given | ||
const firstName = 'Rosario'; | ||
const nickName = 'Charito'; | ||
const target = { | ||
first_name: firstName, | ||
nick_name: nickName, | ||
}; | ||
let result = null; | ||
// When | ||
result = ObjectUtils.snakeToLowerCamelKeys(target); | ||
// Then | ||
expect(result).toEqual({ | ||
firstName, | ||
nickName, | ||
}); | ||
}); | ||
it('should transform specific keys to lower camel case', () => { | ||
// Given | ||
const firstName = 'Rosario'; | ||
const nickName = 'Charito'; | ||
const target = { | ||
name: { | ||
first_name: firstName, | ||
nick_name: nickName, | ||
}, | ||
}; | ||
let result = null; | ||
// When | ||
result = ObjectUtils.snakeToLowerCamelKeys(target, ['name.first_name']); | ||
// Then | ||
expect(result).toEqual({ | ||
name: { | ||
firstName, | ||
nick_name: nickName, | ||
}, | ||
}); | ||
}); | ||
it('should transform all keys to lower camel case except one', () => { | ||
// Given | ||
const firstName = 'Rosario'; | ||
const nickName = 'Charito'; | ||
const target = { | ||
name_info: { | ||
first_name: firstName, | ||
nick_name: nickName, | ||
}, | ||
}; | ||
let result = null; | ||
// When | ||
result = ObjectUtils.snakeToLowerCamelKeys(target, [], ['name_info.first_name']); | ||
// Then | ||
expect(result).toEqual({ | ||
nameInfo: { | ||
first_name: firstName, | ||
nickName, | ||
}, | ||
}); | ||
}); | ||
}); | ||
describe('snakeToDashKeys', () => { | ||
it('should transform all keys to dash case', () => { | ||
// Given | ||
const firstName = 'Rosario'; | ||
const nickName = 'Charito'; | ||
const target = { | ||
first_name: firstName, | ||
nick_name: nickName, | ||
}; | ||
let result = null; | ||
// When | ||
result = ObjectUtils.snakeToDashKeys(target); | ||
// Then | ||
expect(result).toEqual({ | ||
'first-name': firstName, | ||
'nick-name': nickName, | ||
}); | ||
}); | ||
it('should transform specific keys to dash case', () => { | ||
// Given | ||
const firstName = 'Rosario'; | ||
const nickName = 'Charito'; | ||
const target = { | ||
name: { | ||
first_name: firstName, | ||
nick_name: nickName, | ||
}, | ||
}; | ||
let result = null; | ||
// When | ||
result = ObjectUtils.snakeToDashKeys(target, ['name.first_name']); | ||
// Then | ||
expect(result).toEqual({ | ||
name: { | ||
'first-name': firstName, | ||
nick_name: nickName, | ||
}, | ||
}); | ||
}); | ||
it('should transform all keys to dash case except one', () => { | ||
// Given | ||
const firstName = 'Rosario'; | ||
const nickName = 'Charito'; | ||
const target = { | ||
name_info: { | ||
first_name: firstName, | ||
nick_name: nickName, | ||
}, | ||
}; | ||
let result = null; | ||
// When | ||
result = ObjectUtils.snakeToDashKeys(target, [], ['name_info.first_name']); | ||
// Then | ||
expect(result).toEqual({ | ||
'name-info': { | ||
first_name: firstName, | ||
'nick-name': nickName, | ||
}, | ||
}); | ||
}); | ||
}); | ||
describe('dashToLowerCamelKeys', () => { | ||
it('should transform all keys to lower camel case', () => { | ||
// Given | ||
const firstName = 'Rosario'; | ||
const nickName = 'Charito'; | ||
const target = { | ||
'first-name': firstName, | ||
'nick-name': nickName, | ||
}; | ||
let result = null; | ||
// When | ||
result = ObjectUtils.dashToLowerCamelKeys(target); | ||
// Then | ||
expect(result).toEqual({ | ||
firstName, | ||
nickName, | ||
}); | ||
}); | ||
it('should transform specific keys to lower camel case', () => { | ||
// Given | ||
const firstName = 'Rosario'; | ||
const nickName = 'Charito'; | ||
const target = { | ||
name: { | ||
'first-name': firstName, | ||
'nick-name': nickName, | ||
}, | ||
}; | ||
let result = null; | ||
// When | ||
result = ObjectUtils.dashToLowerCamelKeys(target, ['name.first-name']); | ||
// Then | ||
expect(result).toEqual({ | ||
name: { | ||
firstName, | ||
'nick-name': nickName, | ||
}, | ||
}); | ||
}); | ||
it('should transform all keys to lower camel case except one', () => { | ||
// Given | ||
const firstName = 'Rosario'; | ||
const nickName = 'Charito'; | ||
const target = { | ||
'name-info': { | ||
'first-name': firstName, | ||
'nick-name': nickName, | ||
}, | ||
}; | ||
let result = null; | ||
// When | ||
result = ObjectUtils.dashToLowerCamelKeys(target, [], ['name-info.first-name']); | ||
// Then | ||
expect(result).toEqual({ | ||
nameInfo: { | ||
'first-name': firstName, | ||
nickName, | ||
}, | ||
}); | ||
}); | ||
}); | ||
describe('dashToSnakeKeys', () => { | ||
it('should transform all keys to snake case', () => { | ||
// Given | ||
const firstName = 'Rosario'; | ||
const nickName = 'Charito'; | ||
const target = { | ||
'first-name': firstName, | ||
'nick-name': nickName, | ||
}; | ||
let result = null; | ||
// When | ||
result = ObjectUtils.dashToSnakeKeys(target); | ||
// Then | ||
expect(result).toEqual({ | ||
first_name: firstName, | ||
nick_name: nickName, | ||
}); | ||
}); | ||
it('should transform specific keys to snake case', () => { | ||
// Given | ||
const firstName = 'Rosario'; | ||
const nickName = 'Charito'; | ||
const target = { | ||
name: { | ||
'first-name': firstName, | ||
'nick-name': nickName, | ||
}, | ||
}; | ||
let result = null; | ||
// When | ||
result = ObjectUtils.dashToSnakeKeys(target, ['name.first-name']); | ||
// Then | ||
expect(result).toEqual({ | ||
name: { | ||
first_name: firstName, | ||
'nick-name': nickName, | ||
}, | ||
}); | ||
}); | ||
it('should transform all keys to snake case except one', () => { | ||
// Given | ||
const firstName = 'Rosario'; | ||
const nickName = 'Charito'; | ||
const target = { | ||
'name-info': { | ||
'first-name': firstName, | ||
'nick-name': nickName, | ||
}, | ||
}; | ||
let result = null; | ||
// When | ||
result = ObjectUtils.dashToSnakeKeys(target, [], ['name-info.first-name']); | ||
// Then | ||
expect(result).toEqual({ | ||
name_info: { | ||
'first-name': firstName, | ||
nick_name: nickName, | ||
}, | ||
}); | ||
}); | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
609459
8339