@webalternatif/js-core 1.0.0
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.
- package/.babelrc +12 -0
- package/.idea/inspectionProfiles/Project_Default.xml +12 -0
- package/.idea/js-core.iml +8 -0
- package/.idea/modules.xml +8 -0
- package/.idea/php.xml +20 -0
- package/.idea/vcs.xml +6 -0
- package/LICENSE +21 -0
- package/README.md +7 -0
- package/dist/cjs/array.js +116 -0
- package/dist/cjs/dom.js +466 -0
- package/dist/cjs/eventDispatcher.js +96 -0
- package/dist/cjs/i18n.js +50 -0
- package/dist/cjs/index.js +55 -0
- package/dist/cjs/is.js +85 -0
- package/dist/cjs/math.js +92 -0
- package/dist/cjs/random.js +38 -0
- package/dist/cjs/string.js +474 -0
- package/dist/cjs/stringPrototype.js +16 -0
- package/dist/cjs/traversal.js +110 -0
- package/dist/cjs/utils.js +118 -0
- package/dist/esm/array.js +116 -0
- package/dist/esm/dom.js +466 -0
- package/dist/esm/eventDispatcher.js +96 -0
- package/dist/esm/i18n.js +50 -0
- package/dist/esm/index.js +55 -0
- package/dist/esm/is.js +85 -0
- package/dist/esm/math.js +92 -0
- package/dist/esm/random.js +38 -0
- package/dist/esm/string.js +474 -0
- package/dist/esm/stringPrototype.js +16 -0
- package/dist/esm/traversal.js +110 -0
- package/dist/esm/utils.js +118 -0
- package/i18n/agenda/en.js +73 -0
- package/i18n/agenda/fr.js +73 -0
- package/i18n/agenda/index.js +2 -0
- package/i18n/ajaxform/en.js +5 -0
- package/i18n/ajaxform/fr.js +5 -0
- package/i18n/ajaxform/index.js +2 -0
- package/i18n/ajaxupload/en.js +12 -0
- package/i18n/ajaxupload/fr.js +12 -0
- package/i18n/ajaxupload/index.js +2 -0
- package/i18n/autocomplete/en.js +3 -0
- package/i18n/autocomplete/fr.js +3 -0
- package/i18n/autocomplete/index.js +2 -0
- package/i18n/confirm/en.js +5 -0
- package/i18n/confirm/fr.js +5 -0
- package/i18n/confirm/index.js +2 -0
- package/i18n/core/en.js +4 -0
- package/i18n/core/fr.js +4 -0
- package/i18n/core/index.js +2 -0
- package/i18n/datagrid/en.js +8 -0
- package/i18n/datagrid/fr.js +8 -0
- package/i18n/datagrid/index.js +2 -0
- package/i18n/date/en.js +51 -0
- package/i18n/date/fr.js +51 -0
- package/i18n/date/index.js +2 -0
- package/i18n/datetimepicker/en.js +30 -0
- package/i18n/datetimepicker/fr.js +30 -0
- package/i18n/datetimepicker/index.js +2 -0
- package/i18n/dialog/en.js +3 -0
- package/i18n/dialog/fr.js +3 -0
- package/i18n/dialog/index.js +2 -0
- package/i18n/fulldayeventagenda/en.js +73 -0
- package/i18n/fulldayeventagenda/fr.js +73 -0
- package/i18n/fulldayeventagenda/index.js +2 -0
- package/i18n/index.d.ts +4 -0
- package/i18n/index.js +15 -0
- package/i18n/richtexteditor/en.js +58 -0
- package/i18n/richtexteditor/fr.js +58 -0
- package/i18n/richtexteditor/index.js +2 -0
- package/i18n/select/en.js +3 -0
- package/i18n/select/fr.js +3 -0
- package/i18n/select/index.js +2 -0
- package/i18n/timepicker/en.js +3 -0
- package/i18n/timepicker/fr.js +3 -0
- package/i18n/timepicker/index.js +2 -0
- package/i18n/useragenda/en.js +74 -0
- package/i18n/useragenda/fr.js +73 -0
- package/i18n/useragenda/index.js +2 -0
- package/jest.config.js +14 -0
- package/package.json +33 -0
- package/src/array.js +124 -0
- package/src/dom.js +569 -0
- package/src/eventDispatcher.js +118 -0
- package/src/i18n.js +55 -0
- package/src/index.js +33 -0
- package/src/is.js +89 -0
- package/src/math.js +109 -0
- package/src/random.js +40 -0
- package/src/string.js +576 -0
- package/src/stringPrototype.js +15 -0
- package/src/traversal.js +134 -0
- package/src/utils.js +130 -0
- package/tests/array.test.js +326 -0
- package/tests/dom.test.js +239 -0
- package/tests/eventdispatcher.test.js +177 -0
- package/tests/i18n.test.js +132 -0
- package/tests/index.test.js +29 -0
- package/tests/is.test.js +354 -0
- package/tests/math.test.js +221 -0
- package/tests/random.test.js +72 -0
- package/tests/string.test.js +1106 -0
- package/tests/traversal.test.js +517 -0
- package/tests/utils.test.js +371 -0
- package/tsconfig.json +16 -0
- package/types/array.d.ts +8 -0
- package/types/dom.d.ts +241 -0
- package/types/eventDispatcher.d.ts +12 -0
- package/types/i18n.d.ts +4 -0
- package/types/index.d.ts +139 -0
- package/types/is.d.ts +16 -0
- package/types/math.d.ts +7 -0
- package/types/random.d.ts +7 -0
- package/types/string.d.ts +37 -0
- package/types/stringPrototype.d.ts +1 -0
- package/types/traversal.d.ts +7 -0
- package/types/utils.d.ts +7 -0
- package/webpack.config.cjs +31 -0
|
@@ -0,0 +1,517 @@
|
|
|
1
|
+
import {
|
|
2
|
+
each, foreach,
|
|
3
|
+
map,
|
|
4
|
+
extend,
|
|
5
|
+
merge,
|
|
6
|
+
clone, reduce
|
|
7
|
+
} from "../src/traversal.js";
|
|
8
|
+
|
|
9
|
+
describe('traversal methods', () => {
|
|
10
|
+
describe('each()', () => {
|
|
11
|
+
it('should iterate over an array and execute the callback for each element', () => {
|
|
12
|
+
const array = [1, 2, 3];
|
|
13
|
+
const mockCallback = jest.fn();
|
|
14
|
+
|
|
15
|
+
each(array, mockCallback);
|
|
16
|
+
|
|
17
|
+
expect(mockCallback).toHaveBeenCalledTimes(array.length);
|
|
18
|
+
expect(mockCallback).toHaveBeenCalledWith(0, 1, array, 0);
|
|
19
|
+
expect(mockCallback).toHaveBeenCalledWith(1, 2, array, 1);
|
|
20
|
+
expect(mockCallback).toHaveBeenCalledWith(2, 3, array, 2);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('should iterate over an object and execute the callback for each key-value pair', () => {
|
|
24
|
+
const obj = {a: 1, b: 2, c: 3};
|
|
25
|
+
const mockCallback = jest.fn();
|
|
26
|
+
|
|
27
|
+
each(obj, mockCallback);
|
|
28
|
+
|
|
29
|
+
expect(mockCallback).toHaveBeenCalledTimes(Object.keys(obj).length);
|
|
30
|
+
expect(mockCallback).toHaveBeenCalledWith('a', 1, obj, 0);
|
|
31
|
+
expect(mockCallback).toHaveBeenCalledWith('b', 2, obj, 1);
|
|
32
|
+
expect(mockCallback).toHaveBeenCalledWith('c', 3, obj, 2);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('should allow the callback to stop iteration by returning false', () => {
|
|
36
|
+
const mockCallback = jest.fn((key, value) => value !== 2);
|
|
37
|
+
const array = [1, 2, 3];
|
|
38
|
+
|
|
39
|
+
each(array, mockCallback);
|
|
40
|
+
|
|
41
|
+
expect(mockCallback).toHaveBeenCalledTimes(2);
|
|
42
|
+
expect(mockCallback).toHaveBeenCalledWith(0, 1, array, 0);
|
|
43
|
+
expect(mockCallback).toHaveBeenCalledWith(1, 2, array, 1);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('should handle string inputs by treating them as arrays of characters', () => {
|
|
47
|
+
const mockCallback = jest.fn((key, value) => value !== 2);
|
|
48
|
+
const str = 'abc';
|
|
49
|
+
|
|
50
|
+
each(str, mockCallback);
|
|
51
|
+
|
|
52
|
+
expect(mockCallback).toHaveBeenCalledTimes(str.length);
|
|
53
|
+
expect(mockCallback).toHaveBeenCalledWith(0, 'a', str, 0);
|
|
54
|
+
expect(mockCallback).toHaveBeenCalledWith(1, 'b', str, 1);
|
|
55
|
+
expect(mockCallback).toHaveBeenCalledWith(2, 'c', str, 2);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('should bind the callback to the provided context if given', () => {
|
|
59
|
+
const context = Symbol('context');
|
|
60
|
+
const mockCallback = jest.fn(function() {
|
|
61
|
+
return context === this;
|
|
62
|
+
});
|
|
63
|
+
const array = [1, 2, 3];
|
|
64
|
+
|
|
65
|
+
each(array, mockCallback, context);
|
|
66
|
+
|
|
67
|
+
expect(mockCallback).toHaveReturnedWith(true);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('should return the original object or array', () => {
|
|
71
|
+
const array = [1, 2, 3];
|
|
72
|
+
const obj = { a: 1, b: 2, c: 3 };
|
|
73
|
+
|
|
74
|
+
const returnedArray = each(array, jest.fn());
|
|
75
|
+
const returnedObj = each(obj, jest.fn());
|
|
76
|
+
|
|
77
|
+
expect(returnedArray).toBe(array);
|
|
78
|
+
expect(returnedObj).toBe(obj);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it('should skip inherited properties and do nothing', () => {
|
|
82
|
+
const prototype = { inheritedKey: 'value' };
|
|
83
|
+
const obj = Object.create(prototype);
|
|
84
|
+
|
|
85
|
+
const mockCallback = jest.fn();
|
|
86
|
+
|
|
87
|
+
each(obj, mockCallback);
|
|
88
|
+
|
|
89
|
+
expect(mockCallback).not.toHaveBeenCalled();
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
describe('foreach', () => {
|
|
94
|
+
it('should call the callback for each item in an array', () => {
|
|
95
|
+
const mockCallback = jest.fn();
|
|
96
|
+
const array = [10, 20, 30];
|
|
97
|
+
|
|
98
|
+
foreach(array, mockCallback);
|
|
99
|
+
|
|
100
|
+
expect(mockCallback).toHaveBeenCalledTimes(3);
|
|
101
|
+
expect(mockCallback).toHaveBeenNthCalledWith(1, 10, 0, array, 0);
|
|
102
|
+
expect(mockCallback).toHaveBeenNthCalledWith(2, 20, 1, array, 1);
|
|
103
|
+
expect(mockCallback).toHaveBeenNthCalledWith(3, 30, 2, array, 2);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('should call the callback for each property in an object', () => {
|
|
107
|
+
const mockCallback = jest.fn();
|
|
108
|
+
const obj = { a: 1, b: 2, c: 3 };
|
|
109
|
+
|
|
110
|
+
foreach(obj, mockCallback);
|
|
111
|
+
|
|
112
|
+
expect(mockCallback).toHaveBeenCalledTimes(3);
|
|
113
|
+
expect(mockCallback).toHaveBeenNthCalledWith(1, 1, 'a', obj, 0);
|
|
114
|
+
expect(mockCallback).toHaveBeenNthCalledWith(2, 2, 'b', obj, 1);
|
|
115
|
+
expect(mockCallback).toHaveBeenNthCalledWith(3, 3, 'c', obj, 2);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it('should respect the provided context', () => {
|
|
119
|
+
const context = { multiplier: 2 };
|
|
120
|
+
const mockCallback = jest.fn(function (value) {
|
|
121
|
+
return value * this.multiplier;
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
const array = [1, 2, 3];
|
|
125
|
+
foreach(array, mockCallback, context);
|
|
126
|
+
|
|
127
|
+
expect(mockCallback.mock.instances[0]).toBe(context);
|
|
128
|
+
expect(mockCallback).toHaveBeenNthCalledWith(1, 1, 0, array, 0);
|
|
129
|
+
expect(mockCallback).toHaveBeenNthCalledWith(2, 2, 1, array, 1);
|
|
130
|
+
expect(mockCallback).toHaveBeenNthCalledWith(3, 3, 2, array, 2);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it('should handle an empty array without error', () => {
|
|
134
|
+
const mockCallback = jest.fn();
|
|
135
|
+
const array = [];
|
|
136
|
+
|
|
137
|
+
foreach(array, mockCallback);
|
|
138
|
+
|
|
139
|
+
expect(mockCallback).not.toHaveBeenCalled();
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('should handle an empty object without error', () => {
|
|
143
|
+
const mockCallback = jest.fn();
|
|
144
|
+
const obj = {};
|
|
145
|
+
|
|
146
|
+
foreach(obj, mockCallback);
|
|
147
|
+
|
|
148
|
+
expect(mockCallback).not.toHaveBeenCalled();
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it('should return the result of each', () => {
|
|
152
|
+
const obj = { a: 1 };
|
|
153
|
+
const callback = jest.fn();
|
|
154
|
+
|
|
155
|
+
const result = foreach(obj, callback);
|
|
156
|
+
expect(result).toBe(each(obj, callback));
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
describe('map()', () => {
|
|
161
|
+
it('should map over an array and apply the callback', () => {
|
|
162
|
+
const inputArray = [1, 2, 3];
|
|
163
|
+
const mockCallback = jest.fn((index, value) => value * 2);
|
|
164
|
+
const result = map(inputArray, mockCallback);
|
|
165
|
+
|
|
166
|
+
expect(result).toEqual([2, 4, 6]);
|
|
167
|
+
expect(mockCallback).toHaveBeenCalledTimes(inputArray.length);
|
|
168
|
+
expect(mockCallback).toHaveBeenCalledWith(0, 1, inputArray, 0);
|
|
169
|
+
expect(mockCallback).toHaveBeenCalledWith(1, 2, inputArray, 1);
|
|
170
|
+
expect(mockCallback).toHaveBeenCalledWith(2, 3, inputArray, 2);
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
it('should map over an object and apply the callback', () => {
|
|
174
|
+
const inputObject = { a: 1, b: 2, c: 3 };
|
|
175
|
+
const mockCallback = jest.fn((key, value) => `${key}:${value}`);
|
|
176
|
+
const result =map(inputObject, mockCallback);
|
|
177
|
+
|
|
178
|
+
expect(result).toEqual(['a:1', 'b:2', 'c:3']);
|
|
179
|
+
expect(mockCallback).toHaveBeenCalledTimes(Object.keys(inputObject).length);
|
|
180
|
+
expect(mockCallback).toHaveBeenCalledWith('a', 1, inputObject, 0);
|
|
181
|
+
expect(mockCallback).toHaveBeenCalledWith('b', 2, inputObject, 1);
|
|
182
|
+
expect(mockCallback).toHaveBeenCalledWith('c', 3, inputObject, 2);
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
it('should exclude null responses from the results', () => {
|
|
186
|
+
const inputArray = [1, 2, 3];
|
|
187
|
+
const mockCallback = jest.fn((index, value) => (value % 2 === 0 ? null : value));
|
|
188
|
+
const result = map(inputArray, mockCallback);
|
|
189
|
+
|
|
190
|
+
expect(result).toEqual([1, 3]);
|
|
191
|
+
expect(mockCallback).toHaveBeenCalledTimes(inputArray.length);
|
|
192
|
+
})
|
|
193
|
+
|
|
194
|
+
it('should handle an empty array', () => {
|
|
195
|
+
const inputArray = [];
|
|
196
|
+
const mockCallback = jest.fn();
|
|
197
|
+
const result = map(inputArray, mockCallback);
|
|
198
|
+
|
|
199
|
+
expect(result).toEqual([]);
|
|
200
|
+
expect(mockCallback).not.toHaveBeenCalled();
|
|
201
|
+
})
|
|
202
|
+
|
|
203
|
+
it('should bind the callback to the provided context', () => {
|
|
204
|
+
const inputArray = [1, 2, 3];
|
|
205
|
+
const context = { multiplier: 2 };
|
|
206
|
+
const mockCallback = jest.fn(function (index, value) {
|
|
207
|
+
return value * this.multiplier;
|
|
208
|
+
});
|
|
209
|
+
const result = map(inputArray, mockCallback, context);
|
|
210
|
+
|
|
211
|
+
expect(result).toEqual([2, 4, 6]);
|
|
212
|
+
expect(mockCallback).toHaveBeenCalledTimes(inputArray.length);
|
|
213
|
+
})
|
|
214
|
+
|
|
215
|
+
it('should return an empty array if no items produce a result', () => {
|
|
216
|
+
const inputArray = [1, 2, 3];
|
|
217
|
+
const mockCallback = jest.fn(() => null);
|
|
218
|
+
const result = map(inputArray, mockCallback);
|
|
219
|
+
|
|
220
|
+
expect(result).toEqual([]);
|
|
221
|
+
expect(mockCallback).toHaveBeenCalledTimes(inputArray.length);
|
|
222
|
+
})
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
describe('reduce', () => {
|
|
226
|
+
it('should sum all values in an array', () => {
|
|
227
|
+
const arr = [1, 2, 3, 4];
|
|
228
|
+
const result = reduce(arr, (acc, val) => acc + val, 1);
|
|
229
|
+
expect(result).toBe(11);
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
it('should work without an initial value for arrays', () => {
|
|
233
|
+
const arr = [1, 2, 3, 4];
|
|
234
|
+
const result = reduce(arr, (acc, val) => acc + val);
|
|
235
|
+
expect(result).toBe(10);
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
it('should reduce an object\'s values', () => {
|
|
239
|
+
const obj = { a: 1, b: 2, c: 3 };
|
|
240
|
+
const result = reduce(obj, (acc, val) => acc + val, 0);
|
|
241
|
+
expect(result).toBe(6);
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
it('should concatenate strings in an array', () => {
|
|
245
|
+
const arr = ['a', 'b', 'c'];
|
|
246
|
+
const result = reduce(arr, (acc, val) => acc + val, '');
|
|
247
|
+
expect(result).toBe('abc');
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
it('should reduce an object with keys and values', () => {
|
|
251
|
+
const obj = { a: 1, b: 2, c: 3 };
|
|
252
|
+
const result = reduce(obj, (acc, val, key) => {
|
|
253
|
+
acc[key] = val * 2;
|
|
254
|
+
return acc;
|
|
255
|
+
}, {});
|
|
256
|
+
expect(result).toEqual({ a: 2, b: 4, c: 6 });
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
it('should handle empty arrays with initial value', () => {
|
|
260
|
+
const arr = [];
|
|
261
|
+
const result = reduce(arr, (acc, val) => acc + val, 10);
|
|
262
|
+
expect(result).toBe(10);
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
it('should handle empty arrays without initial value', () => {
|
|
266
|
+
const arr = [];
|
|
267
|
+
expect(() => reduce(arr, (acc, val) => acc + val)).toThrow();
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
it('should reduce a Set', () => {
|
|
271
|
+
const set = new Set([1, 2, 3]);
|
|
272
|
+
const result = reduce(set, (acc, val) => acc + val, 0);
|
|
273
|
+
expect(result).toBe(6);
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
it('should reduce a Map\'s values', () => {
|
|
277
|
+
const map = new Map([['a', 1], ['b', 2], ['c', 3]]);
|
|
278
|
+
const result = reduce(map, (acc, val) => acc + val, 0);
|
|
279
|
+
expect(result).toBe(6);
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
it('should handle non-array-like objects gracefully', () => {
|
|
283
|
+
const obj = { a: 1, b: 2, c: 3 };
|
|
284
|
+
const result = reduce(obj, (acc, val) => acc + val, 0);
|
|
285
|
+
expect(result).toBe(6);
|
|
286
|
+
});
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
describe('extend()', () => {
|
|
290
|
+
it('should return the first argument if less than two arguments are provided', () => {
|
|
291
|
+
const obj = { a: 1 };
|
|
292
|
+
expect(extend(obj)).toEqual(obj);
|
|
293
|
+
expect(extend(undefined)).toBeUndefined();
|
|
294
|
+
expect(extend(null)).toBeNull();
|
|
295
|
+
})
|
|
296
|
+
|
|
297
|
+
it('should merge two objects shallowly', () => {
|
|
298
|
+
const obj1 = { a: 1 };
|
|
299
|
+
const obj2 = { b: 2 };
|
|
300
|
+
const result = extend({}, obj1, obj2);
|
|
301
|
+
expect(result).toEqual({ a: 1, b: 2 });
|
|
302
|
+
})
|
|
303
|
+
|
|
304
|
+
it('should overwrite properties in shallow merge', () => {
|
|
305
|
+
const obj1 = { a: 1 };
|
|
306
|
+
const obj2 = { a: 2 };
|
|
307
|
+
const result = extend({}, obj1, obj2);
|
|
308
|
+
expect(result).toEqual({ a: 2 });
|
|
309
|
+
})
|
|
310
|
+
|
|
311
|
+
it('should deep merge nested objects when deep is true', () => {
|
|
312
|
+
const obj1 = { a: { b: 1 } };
|
|
313
|
+
const obj2 = { a: { c: 2 } };
|
|
314
|
+
const result = extend(true, {}, obj1, obj2);
|
|
315
|
+
expect(result).toEqual({ a: { b: 1, c: 2 } });
|
|
316
|
+
})
|
|
317
|
+
|
|
318
|
+
it('should not modify source objects during shallow merge', () => {
|
|
319
|
+
const obj1 = { a: 1 };
|
|
320
|
+
const obj2 = { b: 2 };
|
|
321
|
+
extend({}, obj1, obj2);
|
|
322
|
+
expect(obj1).toEqual({ a: 1 });
|
|
323
|
+
expect(obj2).toEqual({ b: 2 });
|
|
324
|
+
})
|
|
325
|
+
|
|
326
|
+
it('should not modify source objects during deep merge', () => {
|
|
327
|
+
const obj1 = { a: { b: 1 } };
|
|
328
|
+
const obj2 = { a: { c: 2 } };
|
|
329
|
+
extend(true, {}, obj1, obj2);
|
|
330
|
+
expect(obj1).toEqual({ a: { b: 1 } });
|
|
331
|
+
expect(obj2).toEqual({ a: { c: 2 } });
|
|
332
|
+
})
|
|
333
|
+
|
|
334
|
+
it('should handle arrays in shallow merge', () => {
|
|
335
|
+
const obj1 = { a: [1, 2] };
|
|
336
|
+
const obj2 = { b: [3, 4] };
|
|
337
|
+
const result = extend({}, obj1, obj2);
|
|
338
|
+
expect(result).toEqual({ a: [1, 2], b: [3, 4] });
|
|
339
|
+
})
|
|
340
|
+
|
|
341
|
+
it('should handle arrays in deep merge', () => {
|
|
342
|
+
const obj1 = { a: [1, 2] };
|
|
343
|
+
const obj2 = { a: [3, 4] };
|
|
344
|
+
const result = extend(true, {}, obj1, obj2);
|
|
345
|
+
expect(result).toEqual({ a: [3, 4] });
|
|
346
|
+
})
|
|
347
|
+
|
|
348
|
+
it('should skip non-object sources in shallow merge', () => {
|
|
349
|
+
const obj1 = { a: 1 };
|
|
350
|
+
const nonObject = null;
|
|
351
|
+
const result = extend({}, obj1, nonObject);
|
|
352
|
+
expect(result).toEqual({ a: 1 });
|
|
353
|
+
})
|
|
354
|
+
|
|
355
|
+
it('should skip non-object sources in deep merge', () => {
|
|
356
|
+
const obj1 = { a: 1 };
|
|
357
|
+
const nonObject = undefined;
|
|
358
|
+
const result = extend(true, {}, obj1, nonObject);
|
|
359
|
+
expect(result).toEqual({ a: 1 });
|
|
360
|
+
})
|
|
361
|
+
|
|
362
|
+
it('should merge multiple objects', () => {
|
|
363
|
+
const obj1 = { a: 1 };
|
|
364
|
+
const obj2 = { b: 2 };
|
|
365
|
+
const obj3 = { c: 3 };
|
|
366
|
+
const result = extend({}, obj1, obj2, obj3);
|
|
367
|
+
expect(result).toEqual({ a: 1, b: 2, c: 3 });
|
|
368
|
+
})
|
|
369
|
+
|
|
370
|
+
it('should overwrite properties in the correct order', () => {
|
|
371
|
+
const obj1 = { a: 1, b: 2 };
|
|
372
|
+
const obj2 = { b: 3, c: 4 };
|
|
373
|
+
const result = extend({}, obj1, obj2);
|
|
374
|
+
expect(result).toEqual({ a: 1, b: 3, c: 4 });
|
|
375
|
+
})
|
|
376
|
+
|
|
377
|
+
it('should create a new object when the destination is not an object', () => {
|
|
378
|
+
const result = extend(42, { key: 'value' });
|
|
379
|
+
|
|
380
|
+
expect(result).toEqual({ key: 'value' });
|
|
381
|
+
});
|
|
382
|
+
})
|
|
383
|
+
|
|
384
|
+
describe('clone()', () => {
|
|
385
|
+
it('should return the input if it is neither an object nor an array', () => {
|
|
386
|
+
expect(clone(42)).toBe(42);
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
it('should return the input if it is a window object', () => {
|
|
390
|
+
expect(clone(window)).toBe(window);
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
it('should clone a plain object', () => {
|
|
394
|
+
const input = { a: 1, b: 2 };
|
|
395
|
+
const result = clone(input);
|
|
396
|
+
|
|
397
|
+
expect(result).toEqual(input);
|
|
398
|
+
expect(result).not.toBe(input);
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
it('should clone a nested object', () => {
|
|
402
|
+
const input = { a: { b: 2 }, c: 3 };
|
|
403
|
+
const result = clone(input);
|
|
404
|
+
|
|
405
|
+
expect(result).toEqual(input);
|
|
406
|
+
expect(result).not.toBe(input);
|
|
407
|
+
expect(result.a).toEqual(input.a);
|
|
408
|
+
expect(result.a).not.toBe(input.a);
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
it('should clone an array', () => {
|
|
412
|
+
const input = [1, 2, 3];
|
|
413
|
+
const result = clone(input);
|
|
414
|
+
|
|
415
|
+
expect(result).toEqual(input);
|
|
416
|
+
expect(result).not.toBe(input);
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
it('should handle undefined, null input', () => {
|
|
420
|
+
expect(clone(null)).toBe(null);
|
|
421
|
+
expect(clone(undefined)).toBe(undefined);
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
it('should handle mixed types in an object', () => {
|
|
425
|
+
const input = {
|
|
426
|
+
a: 1,
|
|
427
|
+
b: [2, 3],
|
|
428
|
+
c: { d: 4 },
|
|
429
|
+
};
|
|
430
|
+
|
|
431
|
+
const result = clone(input);
|
|
432
|
+
|
|
433
|
+
expect(result).toEqual(input);
|
|
434
|
+
expect(result).not.toBe(input);
|
|
435
|
+
});
|
|
436
|
+
});
|
|
437
|
+
|
|
438
|
+
describe('merge function', () => {
|
|
439
|
+
it('should merge two arrays correctly', () => {
|
|
440
|
+
const first = [1, 2];
|
|
441
|
+
const second = [3, 4];
|
|
442
|
+
|
|
443
|
+
expect(merge(first, second)).toEqual([1, 2, 3, 4]);
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
it('should merge multiple arrays recursively', () => {
|
|
447
|
+
const first = [1];
|
|
448
|
+
const second = [2, 3];
|
|
449
|
+
const third = [4, 5];
|
|
450
|
+
const fourth = [6];
|
|
451
|
+
const expectedResult = [1, 2, 3, 4, 5, 6];
|
|
452
|
+
|
|
453
|
+
const result = merge(first, second, third, fourth);
|
|
454
|
+
expect(result).toEqual(expectedResult);
|
|
455
|
+
});
|
|
456
|
+
|
|
457
|
+
it('should handle empty arrays correctly', () => {
|
|
458
|
+
const first = [];
|
|
459
|
+
const second = [1, 2, 3];
|
|
460
|
+
const expectedResult = [1, 2, 3];
|
|
461
|
+
|
|
462
|
+
const result = merge(first, second);
|
|
463
|
+
expect(result).toEqual(expectedResult);
|
|
464
|
+
|
|
465
|
+
const result2 = merge([], []);
|
|
466
|
+
expect(result2).toEqual([]);
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
it('should handle arrays with mixed data types', () => {
|
|
470
|
+
const first = [1, 'a', { key: 'value' }];
|
|
471
|
+
const second = [true, null, [2, 3]];
|
|
472
|
+
const expectedResult = [1, 'a', { key: 'value' }, true, null, [2, 3]];
|
|
473
|
+
|
|
474
|
+
const result = merge(first, second);
|
|
475
|
+
expect(result).toEqual(expectedResult);
|
|
476
|
+
});
|
|
477
|
+
|
|
478
|
+
it('should not modify the original arrays', () => {
|
|
479
|
+
const first = [1, 2];
|
|
480
|
+
const second = [3, 4];
|
|
481
|
+
|
|
482
|
+
merge(first, second);
|
|
483
|
+
|
|
484
|
+
expect(first).toEqual([1, 2]);
|
|
485
|
+
expect(second).toEqual([3, 4]);
|
|
486
|
+
});
|
|
487
|
+
|
|
488
|
+
it('should return the first array if no additional arrays are provided', () => {
|
|
489
|
+
const first = [1, 2];
|
|
490
|
+
const expectedResult = [1, 2];
|
|
491
|
+
|
|
492
|
+
const result = merge(first);
|
|
493
|
+
expect(result).toEqual(expectedResult);
|
|
494
|
+
});
|
|
495
|
+
|
|
496
|
+
it('should return an empty array if no arrays are provided', () => {
|
|
497
|
+
const expectedResult = [];
|
|
498
|
+
|
|
499
|
+
const result = merge([]);
|
|
500
|
+
expect(result).toEqual(expectedResult);
|
|
501
|
+
});
|
|
502
|
+
|
|
503
|
+
it('should stop iteration when callback returns false for an object', () => {
|
|
504
|
+
const obj = { a: 1, b: 2, c: 3, d: 4 };
|
|
505
|
+
const mockCallback = jest.fn((key, value, originalObj, index) => {
|
|
506
|
+
if (value === 3) return false;
|
|
507
|
+
});
|
|
508
|
+
|
|
509
|
+
each(obj, mockCallback);
|
|
510
|
+
|
|
511
|
+
expect(mockCallback).toHaveBeenCalledTimes(3);
|
|
512
|
+
expect(mockCallback).toHaveBeenCalledWith('a', 1, obj, 0);
|
|
513
|
+
expect(mockCallback).toHaveBeenCalledWith('b', 2, obj, 1);
|
|
514
|
+
expect(mockCallback).toHaveBeenCalledWith('c', 3, obj, 2);
|
|
515
|
+
});
|
|
516
|
+
});
|
|
517
|
+
})
|