@osimatic/helpers-js 1.4.22 → 1.4.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,12 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(npm test)",
5
+ "Bash(npm test:*)",
6
+ "Bash(npm run test:coverage:*)",
7
+ "Bash(npm login)",
8
+ "Bash(npm publish:*)",
9
+ "Bash(npm logout:*)"
10
+ ]
11
+ }
12
+ }
package/CHANGELOG CHANGED
@@ -79,4 +79,5 @@ PostalAddress.setAutocomplete(input, onChange(formatted_address)) -> PostalAddre
79
79
 
80
80
  1.4.0
81
81
  new OpenStreetMap(id) -> new OpenStreetMap(element)
82
- OpenStreetMap.centerOnFrance -> OpenStreetMap.centerMapOnCountry('FR')
82
+ OpenStreetMap.centerOnFrance -> OpenStreetMap.centerMapOnCountry('FR')
83
+ const flagsPath = 'xxx'; -> Country.setFlagsPath('xxx');
package/array.js CHANGED
@@ -31,7 +31,7 @@ Array.prototype.unique = function() {
31
31
  };
32
32
 
33
33
  Array.prototype.removeEmptyValues = function() {
34
- return this.filter(val => val != '');
34
+ return this.filter(val => val !== '');
35
35
  };
36
36
 
37
37
  Array.prototype.hasOwnIndex = function(prop) {
@@ -64,7 +64,7 @@ Array.generate = ({from = 0, to, step = 1, length = Math.ceil((to - from) / step
64
64
 
65
65
  Array.getValuesByKeyInArrayOfArrays = function(array, key) {
66
66
  let listeValues = [];
67
- for (let i in array) {
67
+ for (let i = 0; i < array.length; i++) {
68
68
  let subArray = array[i];
69
69
  if (typeof(subArray[key]) != 'undefined') {
70
70
  listeValues.push(subArray[key]);
package/bank.js CHANGED
@@ -1,14 +1,14 @@
1
1
  class IBAN {
2
2
  static format(iban) {
3
- return iban.replace(/[^\dA-Z]/g, '').replace(/(.{4})/g, '$1 ').trim();
3
+ return iban.toUpperCase().replace(/[^\dA-Z]/g, '').replace(/(.{4})/g, '$1 ').trim();
4
4
  }
5
5
  }
6
6
 
7
7
  class BankCard {
8
- static formatCardNumber(cardNumber) {
8
+ static formatCardNumber(cardNumber, hiddenChar='*') {
9
9
  if (cardNumber.length === 16) {
10
10
  cardNumber = cardNumber.substring(0, 4)+'-'+cardNumber.substring(4, 8)+'-'+cardNumber.substring(8, 12)+'-'+cardNumber.substring(12, 16);
11
- cardNumber = cardNumber.replace(/(\*)/gi, 'X');
11
+ cardNumber = cardNumber.replace(/[*X]/gi, hiddenChar);
12
12
  }
13
13
  return cardNumber;
14
14
  }
@@ -4,10 +4,10 @@ class PersonName {
4
4
  static format(firstName, lastName) {
5
5
  let str = '';
6
6
  if (firstName != null && firstName !== '') {
7
- str += ' '+firstName;
7
+ str += ' '+firstName.trim();
8
8
  }
9
9
  if (lastName != null && lastName !== '') {
10
- str += ' '+lastName;
10
+ str += ' '+lastName.trim();
11
11
  }
12
12
  return str.trim();
13
13
  }
package/http_client.js CHANGED
@@ -289,7 +289,14 @@ class HTTPClient {
289
289
 
290
290
  static download(method, url, data, errorCallback=null, completeCallback=null, additionalHeaders={}) {
291
291
  HTTPClient.requestBlob(method, url, data,
292
- (blobData, response) => File.download(blobData, response.headers.get('content-type'), response.headers.get('content-disposition')),
292
+ (blobData, response) => {
293
+ const contentType = response.headers.get('content-type');
294
+ // Si la réponse est du JSON, on ne télécharge pas de fichier
295
+ if (contentType && contentType.includes('application/json')) {
296
+ return;
297
+ }
298
+ File.download(blobData, contentType, response.headers.get('content-disposition'));
299
+ },
293
300
  errorCallback,
294
301
  completeCallback,
295
302
  additionalHeaders
@@ -346,9 +353,17 @@ class HTTPClient {
346
353
  }
347
354
 
348
355
  if (response.ok) {
349
- const blobData = await response.blob();
350
- if (typeof successCallback == 'function') {
351
- successCallback(blobData, response);
356
+ if (response.headers.get('Content-Type') === 'application/json') {
357
+ const json = await response.json();
358
+ if (typeof successCallback == 'function') {
359
+ successCallback(json, response);
360
+ }
361
+ }
362
+ else {
363
+ const blobData = await response.blob();
364
+ if (typeof successCallback == 'function') {
365
+ successCallback(blobData, response);
366
+ }
352
367
  }
353
368
  }
354
369
  else {
package/location.js CHANGED
@@ -1,7 +1,11 @@
1
1
 
2
2
  class Country {
3
+ static setFlagsPath(flagsPath) {
4
+ Country.flagsPath = flagsPath;
5
+ }
6
+
3
7
  static getFlagPath(countryCode) {
4
- return flagsPath+countryCode.toLowerCase()+'.png';
8
+ return (typeof Country.flagsPath != 'undefined' ? Country.flagsPath : '/')+countryCode.toLowerCase()+'.png';
5
9
  }
6
10
  static getFlagImg(countryCode) {
7
11
  return '<span><img src="'+Country.getFlagPath(countryCode)+'" alt="" title="'+Country.getCountryName(countryCode)+'" class="flag" /></span>'
@@ -613,7 +617,7 @@ class GeographicCoordinates {
613
617
  return null;
614
618
  }
615
619
 
616
- return asString ? str.join(',') : [lat, long];
620
+ return asString ? lat+','+long : [lat, long];
617
621
  }
618
622
 
619
623
  static toFixed(latOrLong, fractionDigit=6) {
package/package.json CHANGED
@@ -1,9 +1,12 @@
1
1
  {
2
2
  "name": "@osimatic/helpers-js",
3
- "version": "1.4.22",
3
+ "version": "1.4.24",
4
4
  "main": "main.js",
5
5
  "scripts": {
6
- "test": "echo \"Error: no test specified\" && exit 1"
6
+ "test": "jest",
7
+ "test:watch": "jest --watch",
8
+ "test:coverage": "jest --coverage",
9
+ "test:verbose": "jest --verbose"
7
10
  },
8
11
  "keywords": [],
9
12
  "author": "",
@@ -11,5 +14,27 @@
11
14
  "description": "",
12
15
  "dependencies": {
13
16
  "ilib": "^14.16.0"
17
+ },
18
+ "devDependencies": {
19
+ "jest": "^30.2.0"
20
+ },
21
+ "jest": {
22
+ "testEnvironment": "node",
23
+ "testMatch": [
24
+ "**/tests/**/*.test.js"
25
+ ],
26
+ "collectCoverageFrom": [
27
+ "*.js",
28
+ "!main.js",
29
+ "!index.js",
30
+ "!node_modules/**",
31
+ "!tests/**"
32
+ ],
33
+ "coverageDirectory": "coverage",
34
+ "coverageReporters": [
35
+ "text",
36
+ "lcov",
37
+ "html"
38
+ ]
14
39
  }
15
40
  }
@@ -0,0 +1,458 @@
1
+ require('../array');
2
+
3
+ describe('Array.prototype extensions', () => {
4
+ describe('unset', () => {
5
+ test('should remove element at given index', () => {
6
+ const arr = [1, 2, 3, 4, 5];
7
+ arr.unset(2);
8
+ expect(arr).toEqual([1, 2, 4, 5]);
9
+ });
10
+
11
+ test('should not modify array if index is -1', () => {
12
+ const arr = [1, 2, 3];
13
+ arr.unset(-1);
14
+ expect(arr).toEqual([1, 2, 3]);
15
+ });
16
+
17
+ test('should not modify array if index is out of bounds', () => {
18
+ const arr = [1, 2, 3];
19
+ arr.unset(10);
20
+ expect(arr).toEqual([1, 2, 3]);
21
+ });
22
+
23
+ test('should remove first element', () => {
24
+ const arr = [1, 2, 3];
25
+ arr.unset(0);
26
+ expect(arr).toEqual([2, 3]);
27
+ });
28
+ });
29
+
30
+ describe('unsetVal', () => {
31
+ test('should remove first occurrence of value', () => {
32
+ const arr = [1, 2, 3, 2, 4];
33
+ arr.unsetVal(2);
34
+ expect(arr).toEqual([1, 3, 2, 4]);
35
+ });
36
+
37
+ test('should not modify array if value not found', () => {
38
+ const arr = [1, 2, 3];
39
+ arr.unsetVal(5);
40
+ expect(arr).toEqual([1, 2, 3]);
41
+ });
42
+
43
+ test('should work with strings', () => {
44
+ const arr = ['a', 'b', 'c'];
45
+ arr.unsetVal('b');
46
+ expect(arr).toEqual(['a', 'c']);
47
+ });
48
+
49
+ test('should work with objects', () => {
50
+ const obj = { id: 1 };
51
+ const arr = [obj, { id: 2 }];
52
+ arr.unsetVal(obj);
53
+ expect(arr).toEqual([{ id: 2 }]);
54
+ });
55
+ });
56
+
57
+ describe('unsetValues', () => {
58
+ test('should remove multiple values', () => {
59
+ const arr = [1, 2, 3, 4, 5];
60
+ arr.unsetValues([2, 4]);
61
+ expect(arr).toEqual([1, 3, 5]);
62
+ });
63
+
64
+ test('should work with empty values array', () => {
65
+ const arr = [1, 2, 3];
66
+ arr.unsetValues([]);
67
+ expect(arr).toEqual([1, 2, 3]);
68
+ });
69
+
70
+ test('should remove only first occurrence of duplicates', () => {
71
+ const arr = [1, 2, 3, 2, 4, 3];
72
+ arr.unsetValues([2, 3]);
73
+ expect(arr).toEqual([1, 2, 4, 3]);
74
+ });
75
+ });
76
+
77
+ describe('pushVal', () => {
78
+ test('should add value if not present', () => {
79
+ const arr = [1, 2, 3];
80
+ arr.pushVal(4);
81
+ expect(arr).toEqual([1, 2, 3, 4]);
82
+ });
83
+
84
+ test('should not add value if already present', () => {
85
+ const arr = [1, 2, 3];
86
+ arr.pushVal(2);
87
+ expect(arr).toEqual([1, 2, 3]);
88
+ });
89
+
90
+ test('should work with strings', () => {
91
+ const arr = ['a', 'b'];
92
+ arr.pushVal('c');
93
+ arr.pushVal('a');
94
+ expect(arr).toEqual(['a', 'b', 'c']);
95
+ });
96
+ });
97
+
98
+ describe('inArray', () => {
99
+ test('should return true if value exists', () => {
100
+ const arr = [1, 2, 3];
101
+ expect(arr.inArray(2)).toBe(true);
102
+ });
103
+
104
+ test('should return false if value does not exist', () => {
105
+ const arr = [1, 2, 3];
106
+ expect(arr.inArray(5)).toBe(false);
107
+ });
108
+
109
+ test('should work with strings', () => {
110
+ const arr = ['a', 'b', 'c'];
111
+ expect(arr.inArray('b')).toBe(true);
112
+ expect(arr.inArray('d')).toBe(false);
113
+ });
114
+
115
+ test('should return false for empty array', () => {
116
+ const arr = [];
117
+ expect(arr.inArray(1)).toBe(false);
118
+ });
119
+ });
120
+
121
+ describe('unique', () => {
122
+ test('should remove duplicate values', () => {
123
+ const arr = [1, 2, 2, 3, 3, 4];
124
+ expect(arr.unique()).toEqual([1, 2, 3, 4]);
125
+ });
126
+
127
+ test('should work with strings', () => {
128
+ const arr = ['a', 'b', 'a', 'c', 'b'];
129
+ expect(arr.unique()).toEqual(['a', 'b', 'c']);
130
+ });
131
+
132
+ test('should work with empty array', () => {
133
+ const arr = [];
134
+ expect(arr.unique()).toEqual([]);
135
+ });
136
+
137
+ test('should not modify original array', () => {
138
+ const arr = [1, 2, 2, 3];
139
+ arr.unique();
140
+ expect(arr).toEqual([1, 2, 2, 3]);
141
+ });
142
+ });
143
+
144
+ describe('removeEmptyValues', () => {
145
+ test('should remove empty strings', () => {
146
+ const arr = ['a', '', 'b', '', 'c'];
147
+ expect(arr.removeEmptyValues()).toEqual(['a', 'b', 'c']);
148
+ });
149
+
150
+ test('should keep other falsy values', () => {
151
+ const arr = ['a', '', 0, false, null, 'b'];
152
+ expect(arr.removeEmptyValues()).toEqual(['a', 0, false, null, 'b']);
153
+ });
154
+
155
+ test('should work with empty array', () => {
156
+ const arr = [];
157
+ expect(arr.removeEmptyValues()).toEqual([]);
158
+ });
159
+ });
160
+
161
+ describe('hasOwnIndex', () => {
162
+ test('should return true for valid array indices', () => {
163
+ const arr = ['a', 'b', 'c'];
164
+ expect(arr.hasOwnIndex('0')).toBe(true);
165
+ expect(arr.hasOwnIndex('1')).toBe(true);
166
+ expect(arr.hasOwnIndex('2')).toBe(true);
167
+ });
168
+
169
+ test('should return false for out of bounds indices', () => {
170
+ const arr = ['a', 'b', 'c'];
171
+ expect(arr.hasOwnIndex('5')).toBe(false);
172
+ });
173
+
174
+ test('should return false for negative indices', () => {
175
+ const arr = ['a', 'b', 'c'];
176
+ expect(arr.hasOwnIndex('-1')).toBe(false);
177
+ });
178
+
179
+ test('should return false for non-numeric strings', () => {
180
+ const arr = ['a', 'b', 'c'];
181
+ expect(arr.hasOwnIndex('abc')).toBe(false);
182
+ });
183
+ });
184
+
185
+ describe('cumulativeSum', () => {
186
+ test('should calculate cumulative sum', () => {
187
+ const arr = [1, 2, 3, 4];
188
+ expect(arr.cumulativeSum()).toEqual([1, 3, 6, 10]);
189
+ });
190
+
191
+ test('should work with negative numbers', () => {
192
+ const arr = [1, -2, 3, -4];
193
+ expect(arr.cumulativeSum()).toEqual([1, -1, 2, -2]);
194
+ });
195
+
196
+ test('should work with decimals', () => {
197
+ const arr = [1.5, 2.5, 3];
198
+ expect(arr.cumulativeSum()).toEqual([1.5, 4, 7]);
199
+ });
200
+
201
+ test('should work with empty array', () => {
202
+ const arr = [];
203
+ expect(arr.cumulativeSum()).toEqual([]);
204
+ });
205
+ });
206
+
207
+ describe('intersect', () => {
208
+ test('should return common elements', () => {
209
+ const arr = [];
210
+ const result = arr.intersect([1, 2, 3, 4], [3, 4, 5, 6]);
211
+ expect(result).toEqual([3, 4]);
212
+ });
213
+
214
+ test('should return empty array if no common elements', () => {
215
+ const arr = [];
216
+ const result = arr.intersect([1, 2], [3, 4]);
217
+ expect(result).toEqual([]);
218
+ });
219
+
220
+ test('should work with strings', () => {
221
+ const arr = [];
222
+ const result = arr.intersect(['a', 'b', 'c'], ['b', 'c', 'd']);
223
+ expect(result).toEqual(['b', 'c']);
224
+ });
225
+
226
+ test('should work with empty arrays', () => {
227
+ const arr = [];
228
+ expect(arr.intersect([], [1, 2])).toEqual([]);
229
+ expect(arr.intersect([1, 2], [])).toEqual([]);
230
+ });
231
+ });
232
+
233
+ describe('diff', () => {
234
+ test('should return symmetric difference', () => {
235
+ const arr = [];
236
+ const result = arr.diff([1, 2, 3], [2, 3, 4]);
237
+ expect(result).toEqual([1, 4]);
238
+ });
239
+
240
+ test('should return all elements if no common elements', () => {
241
+ const arr = [];
242
+ const result = arr.diff([1, 2], [3, 4]);
243
+ expect(result).toEqual([1, 2, 3, 4]);
244
+ });
245
+
246
+ test('should work with strings', () => {
247
+ const arr = [];
248
+ const result = arr.diff(['a', 'b', 'c'], ['b', 'c', 'd']);
249
+ expect(result).toEqual(['a', 'd']);
250
+ });
251
+
252
+ test('should work with empty arrays', () => {
253
+ const arr = [];
254
+ expect(arr.diff([], [1, 2])).toEqual([1, 2]);
255
+ expect(arr.diff([1, 2], [])).toEqual([1, 2]);
256
+ });
257
+ });
258
+
259
+ describe('filterUnique', () => {
260
+ test('should filter duplicate values', () => {
261
+ const arr = [1, 2, 2, 3, 3, 4];
262
+ expect(arr.filterUnique()).toEqual([1, 2, 3, 4]);
263
+ });
264
+
265
+ test('should work with strings', () => {
266
+ const arr = ['a', 'b', 'a', 'c'];
267
+ expect(arr.filterUnique()).toEqual(['a', 'b', 'c']);
268
+ });
269
+
270
+ test('should work with empty array', () => {
271
+ const arr = [];
272
+ expect(arr.filterUnique()).toEqual([]);
273
+ });
274
+ });
275
+ });
276
+
277
+ describe('Array static methods', () => {
278
+ describe('generate', () => {
279
+ test('should generate array from 0 to given number', () => {
280
+ const result = Array.generate({ to: 5 });
281
+ expect(result).toEqual([0, 1, 2, 3, 4]);
282
+ });
283
+
284
+ test('should generate array with custom start', () => {
285
+ const result = Array.generate({ from: 5, to: 10 });
286
+ expect(result).toEqual([5, 6, 7, 8, 9]);
287
+ });
288
+
289
+ test('should generate array with custom step', () => {
290
+ const result = Array.generate({ from: 0, to: 10, step: 2 });
291
+ expect(result).toEqual([0, 2, 4, 6, 8]);
292
+ });
293
+
294
+ test('should generate array with negative step', () => {
295
+ const result = Array.generate({ from: 10, to: 0, step: -2 });
296
+ expect(result).toEqual([10, 8, 6, 4, 2]);
297
+ });
298
+
299
+ test('should generate array with decimal step', () => {
300
+ const result = Array.generate({ from: 0, to: 2, step: 0.5 });
301
+ expect(result).toEqual([0, 0.5, 1, 1.5]);
302
+ });
303
+
304
+ test('should work with custom length', () => {
305
+ const result = Array.generate({ from: 0, step: 3, length: 4 });
306
+ expect(result).toEqual([0, 3, 6, 9]);
307
+ });
308
+ });
309
+
310
+ describe('getValuesByKeyInArrayOfArrays', () => {
311
+ test('should extract values by key', () => {
312
+ const arr = [
313
+ { id: 1, name: 'Alice' },
314
+ { id: 2, name: 'Bob' },
315
+ { id: 3, name: 'Charlie' }
316
+ ];
317
+ const result = Array.getValuesByKeyInArrayOfArrays(arr, 'name');
318
+ expect(result).toEqual(['Alice', 'Bob', 'Charlie']);
319
+ });
320
+
321
+ test('should skip elements without the key', () => {
322
+ const arr = [
323
+ { id: 1, name: 'Alice' },
324
+ { id: 2 },
325
+ { id: 3, name: 'Charlie' }
326
+ ];
327
+ const result = Array.getValuesByKeyInArrayOfArrays(arr, 'name');
328
+ expect(result).toEqual(['Alice', 'Charlie']);
329
+ });
330
+
331
+ test('should work with empty array', () => {
332
+ const result = Array.getValuesByKeyInArrayOfArrays([], 'name');
333
+ expect(result).toEqual([]);
334
+ });
335
+
336
+ test('should work with numeric keys', () => {
337
+ const arr = [
338
+ { 0: 'a', 1: 'b' },
339
+ { 0: 'c', 1: 'd' }
340
+ ];
341
+ const result = Array.getValuesByKeyInArrayOfArrays(arr, 0);
342
+ expect(result).toEqual(['a', 'c']);
343
+ });
344
+ });
345
+ });
346
+
347
+ describe('Object extensions', () => {
348
+ describe('toArray', () => {
349
+ test('should convert object values to array', () => {
350
+ const obj = { a: 1, b: 2, c: 3 };
351
+ expect(Object.toArray(obj)).toEqual([1, 2, 3]);
352
+ });
353
+
354
+ test('should work with empty object', () => {
355
+ expect(Object.toArray({})).toEqual([]);
356
+ });
357
+
358
+ test('should preserve order for numeric keys', () => {
359
+ const obj = { 0: 'a', 1: 'b', 2: 'c' };
360
+ expect(Object.toArray(obj)).toEqual(['a', 'b', 'c']);
361
+ });
362
+ });
363
+
364
+ describe('filter', () => {
365
+ test('should filter object by value predicate', () => {
366
+ const obj = { a: 1, b: 2, c: 3, d: 4 };
367
+ const result = Object.filter(obj, val => val > 2);
368
+ expect(result).toEqual({ c: 3, d: 4 });
369
+ });
370
+
371
+ test('should work with string values', () => {
372
+ const obj = { a: 'apple', b: 'banana', c: 'cherry' };
373
+ const result = Object.filter(obj, val => val.startsWith('a'));
374
+ expect(result).toEqual({ a: 'apple' });
375
+ });
376
+
377
+ test('should return empty object if no match', () => {
378
+ const obj = { a: 1, b: 2 };
379
+ const result = Object.filter(obj, val => val > 10);
380
+ expect(result).toEqual({});
381
+ });
382
+
383
+ test('should work with empty object', () => {
384
+ const result = Object.filter({}, val => val > 0);
385
+ expect(result).toEqual({});
386
+ });
387
+ });
388
+
389
+ describe('filterKeys', () => {
390
+ test('should filter object by key predicate', () => {
391
+ const obj = { a: 1, b: 2, c: 3, d: 4 };
392
+ const result = Object.filterKeys(obj, key => key === 'a' || key === 'c');
393
+ expect(result).toEqual({ a: 1, c: 3 });
394
+ });
395
+
396
+ test('should work with pattern matching', () => {
397
+ const obj = { name: 'John', age: 30, name2: 'Doe' };
398
+ const result = Object.filterKeys(obj, key => key.includes('name'));
399
+ expect(result).toEqual({ name: 'John', name2: 'Doe' });
400
+ });
401
+
402
+ test('should return empty object if no match', () => {
403
+ const obj = { a: 1, b: 2 };
404
+ const result = Object.filterKeys(obj, key => key === 'z');
405
+ expect(result).toEqual({});
406
+ });
407
+ });
408
+
409
+ describe('renameKeys', () => {
410
+ test('should rename keys according to map', () => {
411
+ const obj = { a: 1, b: 2, c: 3 };
412
+ const result = Object.renameKeys(obj, { a: 'x', b: 'y' });
413
+ expect(result).toEqual({ x: 1, y: 2, c: 3 });
414
+ });
415
+
416
+ test('should keep keys not in map', () => {
417
+ const obj = { firstName: 'John', lastName: 'Doe', age: 30 };
418
+ const result = Object.renameKeys(obj, { firstName: 'first', lastName: 'last' });
419
+ expect(result).toEqual({ first: 'John', last: 'Doe', age: 30 });
420
+ });
421
+
422
+ test('should work with empty map', () => {
423
+ const obj = { a: 1, b: 2 };
424
+ const result = Object.renameKeys(obj, {});
425
+ expect(result).toEqual({ a: 1, b: 2 });
426
+ });
427
+
428
+ test('should work with empty object', () => {
429
+ const result = Object.renameKeys({}, { a: 'x' });
430
+ expect(result).toEqual({});
431
+ });
432
+ });
433
+
434
+ describe('renameKeysByCallback', () => {
435
+ test('should rename keys using callback', () => {
436
+ const obj = { a: 1, b: 2, c: 3 };
437
+ const result = Object.renameKeysByCallback(obj, key => key.toUpperCase());
438
+ expect(result).toEqual({ A: 1, B: 2, C: 3 });
439
+ });
440
+
441
+ test('should add prefix to keys', () => {
442
+ const obj = { name: 'John', age: 30 };
443
+ const result = Object.renameKeysByCallback(obj, key => 'user_' + key);
444
+ expect(result).toEqual({ user_name: 'John', user_age: 30 });
445
+ });
446
+
447
+ test('should work with complex transformations', () => {
448
+ const obj = { firstName: 'John', lastName: 'Doe' };
449
+ const result = Object.renameKeysByCallback(obj, key => key.replace(/([A-Z])/g, '_$1').toLowerCase());
450
+ expect(result).toEqual({ first_name: 'John', last_name: 'Doe' });
451
+ });
452
+
453
+ test('should work with empty object', () => {
454
+ const result = Object.renameKeysByCallback({}, key => key.toUpperCase());
455
+ expect(result).toEqual({});
456
+ });
457
+ });
458
+ });