@osimatic/helpers-js 1.4.24 → 1.4.25

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.
Files changed (114) hide show
  1. package/.claude/settings.local.json +2 -1
  2. package/chartjs.js +1 -1
  3. package/date_time.js +25 -16
  4. package/draw.js +3 -2
  5. package/duration.js +12 -15
  6. package/event_bus.js +2 -2
  7. package/file.js +1 -1
  8. package/form_helper.js +1 -1
  9. package/http_client.js +2 -0
  10. package/jwt.js +18 -6
  11. package/media.js +1 -1
  12. package/number.js +2 -3
  13. package/package.json +3 -2
  14. package/social_network.js +5 -0
  15. package/string.js +11 -2
  16. package/tests/chartjs.test.js +273 -0
  17. package/tests/date_time/DatePeriod.test.js +179 -0
  18. package/tests/date_time/DateTime.test.js +492 -0
  19. package/tests/date_time/SqlDate.test.js +205 -0
  20. package/tests/date_time/SqlDateTime.test.js +326 -0
  21. package/tests/date_time/SqlTime.test.js +162 -0
  22. package/tests/date_time/TimestampUnix.test.js +262 -0
  23. package/tests/draw.test.js +271 -0
  24. package/tests/duration.test.js +365 -0
  25. package/tests/event_bus.test.js +268 -0
  26. package/tests/file.test.js +358 -0
  27. package/tests/form_date.test.js +417 -0
  28. package/tests/form_helper.test.js +415 -0
  29. package/tests/http_client.test.js +570 -0
  30. package/tests/jwt.test.js +804 -0
  31. package/tests/media.test.js +458 -0
  32. package/tests/network.test.js +489 -0
  33. package/tests/number.test.js +448 -0
  34. package/tests/open_street_map.test.js +388 -0
  35. package/tests/shopping_cart.test.js +355 -0
  36. package/tests/social_network.test.js +333 -0
  37. package/tests/string.test.js +473 -0
  38. package/tests/user.test.js +204 -0
  39. package/tests/util.test.js +99 -0
  40. package/tests/visitor.test.js +508 -0
  41. package/tmpclaude-00a6-cwd +1 -0
  42. package/tmpclaude-0526-cwd +1 -0
  43. package/tmpclaude-0973-cwd +1 -0
  44. package/tmpclaude-0b61-cwd +1 -0
  45. package/tmpclaude-146f-cwd +1 -0
  46. package/tmpclaude-223d-cwd +1 -0
  47. package/tmpclaude-2330-cwd +1 -0
  48. package/tmpclaude-282a-cwd +1 -0
  49. package/tmpclaude-2846-cwd +1 -0
  50. package/tmpclaude-28a6-cwd +1 -0
  51. package/tmpclaude-2b5a-cwd +1 -0
  52. package/tmpclaude-2def-cwd +1 -0
  53. package/tmpclaude-3906-cwd +1 -0
  54. package/tmpclaude-3b32-cwd +1 -0
  55. package/tmpclaude-3da9-cwd +1 -0
  56. package/tmpclaude-3dc3-cwd +1 -0
  57. package/tmpclaude-3e3b-cwd +1 -0
  58. package/tmpclaude-43b6-cwd +1 -0
  59. package/tmpclaude-4495-cwd +1 -0
  60. package/tmpclaude-462f-cwd +1 -0
  61. package/tmpclaude-4b29-cwd +1 -0
  62. package/tmpclaude-4db5-cwd +1 -0
  63. package/tmpclaude-4e01-cwd +1 -0
  64. package/tmpclaude-5101-cwd +1 -0
  65. package/tmpclaude-524f-cwd +1 -0
  66. package/tmpclaude-5636-cwd +1 -0
  67. package/tmpclaude-5cdd-cwd +1 -0
  68. package/tmpclaude-5f1f-cwd +1 -0
  69. package/tmpclaude-6078-cwd +1 -0
  70. package/tmpclaude-622e-cwd +1 -0
  71. package/tmpclaude-6802-cwd +1 -0
  72. package/tmpclaude-6e36-cwd +1 -0
  73. package/tmpclaude-7793-cwd +1 -0
  74. package/tmpclaude-7f96-cwd +1 -0
  75. package/tmpclaude-8566-cwd +1 -0
  76. package/tmpclaude-8874-cwd +1 -0
  77. package/tmpclaude-8915-cwd +1 -0
  78. package/tmpclaude-8c8b-cwd +1 -0
  79. package/tmpclaude-94df-cwd +1 -0
  80. package/tmpclaude-9859-cwd +1 -0
  81. package/tmpclaude-9ac5-cwd +1 -0
  82. package/tmpclaude-9f18-cwd +1 -0
  83. package/tmpclaude-a202-cwd +1 -0
  84. package/tmpclaude-a741-cwd +1 -0
  85. package/tmpclaude-ab5f-cwd +1 -0
  86. package/tmpclaude-b008-cwd +1 -0
  87. package/tmpclaude-b0a1-cwd +1 -0
  88. package/tmpclaude-b63d-cwd +1 -0
  89. package/tmpclaude-b681-cwd +1 -0
  90. package/tmpclaude-b72d-cwd +1 -0
  91. package/tmpclaude-b92f-cwd +1 -0
  92. package/tmpclaude-bc49-cwd +1 -0
  93. package/tmpclaude-bc50-cwd +1 -0
  94. package/tmpclaude-bccf-cwd +1 -0
  95. package/tmpclaude-be55-cwd +1 -0
  96. package/tmpclaude-c228-cwd +1 -0
  97. package/tmpclaude-c717-cwd +1 -0
  98. package/tmpclaude-c7ce-cwd +1 -0
  99. package/tmpclaude-cf3e-cwd +1 -0
  100. package/tmpclaude-d142-cwd +1 -0
  101. package/tmpclaude-d5bc-cwd +1 -0
  102. package/tmpclaude-d6ae-cwd +1 -0
  103. package/tmpclaude-d77a-cwd +1 -0
  104. package/tmpclaude-d8da-cwd +1 -0
  105. package/tmpclaude-dbdb-cwd +1 -0
  106. package/tmpclaude-de61-cwd +1 -0
  107. package/tmpclaude-de81-cwd +1 -0
  108. package/tmpclaude-df9d-cwd +1 -0
  109. package/tmpclaude-e786-cwd +1 -0
  110. package/tmpclaude-f01d-cwd +1 -0
  111. package/tmpclaude-f2a9-cwd +1 -0
  112. package/tmpclaude-fc36-cwd +1 -0
  113. package/tmpclaude-ffef-cwd +1 -0
  114. package/visitor.js +2 -2
@@ -0,0 +1,489 @@
1
+ const { Cookie, UrlAndQueryString } = require('../network');
2
+
3
+ describe('Cookie', () => {
4
+ // Mock document.cookie
5
+ let cookieStore = {};
6
+
7
+ beforeEach(() => {
8
+ cookieStore = {};
9
+
10
+ Object.defineProperty(global, 'document', {
11
+ value: {
12
+ get cookie() {
13
+ return Object.entries(cookieStore).map(([key, value]) => `${key}=${value}`).join('; ');
14
+ },
15
+ set cookie(value) {
16
+ const match = value.match(/([^=]+)=([^;]*)/);
17
+ if (match) {
18
+ const [, key, val] = match;
19
+ // Check if expires date is in the past
20
+ const expiresMatch = value.match(/expires=([^;]+)/);
21
+ if (expiresMatch) {
22
+ const expiresDate = new Date(expiresMatch[1]);
23
+ if (expiresDate < new Date()) {
24
+ delete cookieStore[key];
25
+ return;
26
+ }
27
+ }
28
+ cookieStore[key] = val;
29
+ }
30
+ }
31
+ },
32
+ writable: true,
33
+ configurable: true
34
+ });
35
+ });
36
+
37
+ describe('set', () => {
38
+ test('should set a cookie with default validity', () => {
39
+ Cookie.set('testCookie', 'testValue');
40
+ expect(cookieStore['testCookie']).toBe('testValue');
41
+ });
42
+
43
+ test('should set a cookie with custom validity days', () => {
44
+ Cookie.set('testCookie', 'testValue', 7);
45
+ expect(cookieStore['testCookie']).toBe('testValue');
46
+ });
47
+
48
+ test('should set cookie with empty value', () => {
49
+ Cookie.set('emptyCookie', '');
50
+ expect(cookieStore['emptyCookie']).toBe('');
51
+ });
52
+
53
+ test('should set cookie with numeric value', () => {
54
+ Cookie.set('numericCookie', '123');
55
+ expect(cookieStore['numericCookie']).toBe('123');
56
+ });
57
+ });
58
+
59
+ describe('get', () => {
60
+ test('should get an existing cookie', () => {
61
+ cookieStore['testCookie'] = 'testValue';
62
+ expect(Cookie.get('testCookie')).toBe('testValue');
63
+ });
64
+
65
+ test('should return null for non-existent cookie', () => {
66
+ expect(Cookie.get('nonExistent')).toBeNull();
67
+ });
68
+
69
+ test('should handle cookies with spaces in name', () => {
70
+ cookieStore['test Cookie'] = 'value';
71
+ expect(Cookie.get('test Cookie')).toBe('value');
72
+ });
73
+
74
+ test('should handle empty cookie value', () => {
75
+ cookieStore['emptyCookie'] = '';
76
+ expect(Cookie.get('emptyCookie')).toBe('');
77
+ });
78
+ });
79
+
80
+ describe('erase', () => {
81
+ test('should erase an existing cookie', () => {
82
+ cookieStore['testCookie'] = 'testValue';
83
+ Cookie.erase('testCookie');
84
+ expect(cookieStore['testCookie']).toBeUndefined();
85
+ });
86
+
87
+ test('should handle erasing non-existent cookie', () => {
88
+ expect(() => Cookie.erase('nonExistent')).not.toThrow();
89
+ });
90
+ });
91
+ });
92
+
93
+ describe('UrlAndQueryString', () => {
94
+ describe('displayUrl', () => {
95
+ test('should display URL with link by default', () => {
96
+ const result = UrlAndQueryString.displayUrl('https://example.com/path');
97
+ expect(result).toContain('<a href="https://example.com/path">');
98
+ expect(result).toContain('example.com');
99
+ expect(result).toContain('</a>');
100
+ });
101
+
102
+ test('should display URL without link', () => {
103
+ const result = UrlAndQueryString.displayUrl('https://example.com/path', false);
104
+ expect(result).not.toContain('<a');
105
+ expect(result).toBe('example.com');
106
+ });
107
+
108
+ test('should handle URL with port', () => {
109
+ const result = UrlAndQueryString.displayUrl('https://example.com:8080/path', false);
110
+ expect(result).toBe('example.com:8080');
111
+ });
112
+
113
+ test('should handle URL with subdomain', () => {
114
+ const result = UrlAndQueryString.displayUrl('https://sub.example.com/path', false);
115
+ expect(result).toBe('sub.example.com');
116
+ });
117
+ });
118
+
119
+ describe('displayUrlAndPath', () => {
120
+ test('should display URL and path with link', () => {
121
+ const result = UrlAndQueryString.displayUrlAndPath('https://example.com/path/to/page');
122
+ expect(result).toContain('<a href="https://example.com/path/to/page">');
123
+ expect(result).toContain('example.com/path/to/page');
124
+ expect(result).toContain('</a>');
125
+ });
126
+
127
+ test('should display URL and path without link', () => {
128
+ const result = UrlAndQueryString.displayUrlAndPath('https://example.com/path/to/page', false);
129
+ expect(result).toBe('example.com/path/to/page');
130
+ });
131
+
132
+ test('should remove trailing slash when path is root and displayPathIfEmpty is false', () => {
133
+ const result = UrlAndQueryString.displayUrlAndPath('https://example.com/', false, false);
134
+ expect(result).toBe('example.com');
135
+ });
136
+
137
+ test('should keep trailing slash when displayPathIfEmpty is true', () => {
138
+ const result = UrlAndQueryString.displayUrlAndPath('https://example.com/', false, true);
139
+ expect(result).toBe('example.com/');
140
+ });
141
+
142
+ test('should handle URL with query string', () => {
143
+ const result = UrlAndQueryString.displayUrlAndPath('https://example.com/path?query=1', false);
144
+ expect(result).toBe('example.com/path');
145
+ });
146
+ });
147
+
148
+ describe('urlify', () => {
149
+ test('should convert URLs to links in text', () => {
150
+ const text = 'Visit https://example.com for more info';
151
+ const result = UrlAndQueryString.urlify(text);
152
+ expect(result).toContain('<a href="https://example.com">https://example.com</a>');
153
+ });
154
+
155
+ test('should handle multiple URLs in text', () => {
156
+ const text = 'Visit https://example.com and https://test.com';
157
+ const result = UrlAndQueryString.urlify(text);
158
+ expect(result).toContain('<a href="https://example.com">');
159
+ expect(result).toContain('<a href="https://test.com">');
160
+ });
161
+
162
+ test('should handle HTTP and HTTPS URLs', () => {
163
+ const text = 'http://example.com and https://example.com';
164
+ const result = UrlAndQueryString.urlify(text);
165
+ expect(result).toContain('<a href="http://example.com">');
166
+ expect(result).toContain('<a href="https://example.com">');
167
+ });
168
+
169
+ test('should not modify text without URLs', () => {
170
+ const text = 'No URLs here';
171
+ const result = UrlAndQueryString.urlify(text);
172
+ expect(result).toBe('No URLs here');
173
+ });
174
+ });
175
+
176
+ describe('getHost', () => {
177
+ test('should get host with protocol', () => {
178
+ const result = UrlAndQueryString.getHost('https://example.com/path');
179
+ expect(result).toBe('https://example.com');
180
+ });
181
+
182
+ test('should get host without protocol', () => {
183
+ const result = UrlAndQueryString.getHost('https://example.com/path', false);
184
+ expect(result).toBe('example.com');
185
+ });
186
+
187
+ test('should handle URL with port', () => {
188
+ const result = UrlAndQueryString.getHost('https://example.com:8080/path', false);
189
+ expect(result).toBe('example.com:8080');
190
+ });
191
+
192
+ test('should handle URL with subdomain', () => {
193
+ const result = UrlAndQueryString.getHost('https://sub.example.com/path', false);
194
+ expect(result).toBe('sub.example.com');
195
+ });
196
+
197
+ test('should handle HTTP protocol', () => {
198
+ const result = UrlAndQueryString.getHost('http://example.com/path');
199
+ expect(result).toBe('http://example.com');
200
+ });
201
+ });
202
+
203
+ describe('getPath', () => {
204
+ test('should get path from URL', () => {
205
+ const result = UrlAndQueryString.getPath('https://example.com/path/to/page');
206
+ expect(result).toBe('/path/to/page');
207
+ });
208
+
209
+ test('should return root path for URL without path', () => {
210
+ const result = UrlAndQueryString.getPath('https://example.com');
211
+ expect(result).toBe('/');
212
+ });
213
+
214
+ test('should handle URL with query string', () => {
215
+ const result = UrlAndQueryString.getPath('https://example.com/path?query=1');
216
+ expect(result).toBe('/path');
217
+ });
218
+
219
+ test('should handle URL with fragment', () => {
220
+ const result = UrlAndQueryString.getPath('https://example.com/path#section');
221
+ expect(result).toBe('/path');
222
+ });
223
+ });
224
+
225
+ describe('getQueryString', () => {
226
+ test('should get query string from URL', () => {
227
+ const result = UrlAndQueryString.getQueryString('https://example.com/path?query=1&param=2');
228
+ expect(result).toBe('?query=1&param=2');
229
+ });
230
+
231
+ test('should return empty string for URL without query', () => {
232
+ const result = UrlAndQueryString.getQueryString('https://example.com/path');
233
+ expect(result).toBe('');
234
+ });
235
+
236
+ test('should handle URL with fragment', () => {
237
+ const result = UrlAndQueryString.getQueryString('https://example.com/path?query=1#section');
238
+ expect(result).toBe('?query=1');
239
+ });
240
+
241
+ test('should handle empty query string', () => {
242
+ const result = UrlAndQueryString.getQueryString('https://example.com/path?');
243
+ expect(result).toBe('');
244
+ });
245
+ });
246
+
247
+ describe('getHostAndPath', () => {
248
+ test('should get host and path with protocol', () => {
249
+ const result = UrlAndQueryString.getHostAndPath('https://example.com/path/to/page');
250
+ expect(result).toBe('https://example.com/path/to/page');
251
+ });
252
+
253
+ test('should get host and path without protocol', () => {
254
+ const result = UrlAndQueryString.getHostAndPath('https://example.com/path/to/page', false);
255
+ expect(result).toBe('example.com/path/to/page');
256
+ });
257
+
258
+ test('should exclude query string', () => {
259
+ const result = UrlAndQueryString.getHostAndPath('https://example.com/path?query=1', false);
260
+ expect(result).toBe('example.com/path');
261
+ });
262
+
263
+ test('should handle root path', () => {
264
+ const result = UrlAndQueryString.getHostAndPath('https://example.com/', false);
265
+ expect(result).toBe('example.com/');
266
+ });
267
+ });
268
+
269
+ describe('getParam', () => {
270
+ test('should get parameter from URL', () => {
271
+ const result = UrlAndQueryString.getParam('query', 'https://example.com/path?query=value&other=test');
272
+ expect(result).toBe('value');
273
+ });
274
+
275
+ test('should return null for non-existent parameter', () => {
276
+ const result = UrlAndQueryString.getParam('missing', 'https://example.com/path?query=value');
277
+ expect(result).toBeNull();
278
+ });
279
+
280
+ test('should handle parameters with special characters', () => {
281
+ const result = UrlAndQueryString.getParam('query', 'https://example.com/path?query=hello%20world');
282
+ expect(result).toBe('hello world');
283
+ });
284
+
285
+ test('should handle empty parameter value', () => {
286
+ const result = UrlAndQueryString.getParam('query', 'https://example.com/path?query=');
287
+ expect(result).toBe('');
288
+ });
289
+
290
+ test('should handle parameter without value', () => {
291
+ const result = UrlAndQueryString.getParam('query', 'https://example.com/path?query');
292
+ expect(result).toBe('');
293
+ });
294
+ });
295
+
296
+ describe('deleteParam', () => {
297
+ test('should delete parameter from query string', () => {
298
+ const result = UrlAndQueryString.deleteParam('?query=1&param=2&other=3', 'param');
299
+ expect(result).not.toContain('param=2');
300
+ expect(result).toContain('query=1');
301
+ expect(result).toContain('other=3');
302
+ });
303
+
304
+ test('should handle deleting non-existent parameter', () => {
305
+ const result = UrlAndQueryString.deleteParam('?query=1&param=2', 'missing');
306
+ expect(result).toContain('query=1');
307
+ expect(result).toContain('param=2');
308
+ });
309
+
310
+ test('should handle deleting only parameter', () => {
311
+ const result = UrlAndQueryString.deleteParam('?query=1', 'query');
312
+ expect(result).toBe('');
313
+ });
314
+ });
315
+
316
+ describe('deleteParamOfUrl', () => {
317
+ test('should delete parameter from URL', () => {
318
+ const result = UrlAndQueryString.deleteParamOfUrl('param', 'https://example.com/path?query=1&param=2&other=3');
319
+ expect(result).not.toContain('param=2');
320
+ expect(result).toContain('https://example.com/path?');
321
+ expect(result).toContain('query=1');
322
+ });
323
+
324
+ test('should preserve host and path', () => {
325
+ const result = UrlAndQueryString.deleteParamOfUrl('param', 'https://example.com/path?param=1');
326
+ expect(result).toContain('https://example.com/path');
327
+ });
328
+ });
329
+
330
+ describe('deleteParamsOfUrl', () => {
331
+ test('should delete multiple parameters from URL', () => {
332
+ const result = UrlAndQueryString.deleteParamsOfUrl(
333
+ ['param1', 'param2'],
334
+ 'https://example.com/path?query=1&param1=2&param2=3&other=4'
335
+ );
336
+ expect(result).not.toContain('param1');
337
+ expect(result).not.toContain('param2');
338
+ expect(result).toContain('query=1');
339
+ expect(result).toContain('other=4');
340
+ });
341
+
342
+ test('should handle empty array', () => {
343
+ const result = UrlAndQueryString.deleteParamsOfUrl([], 'https://example.com/path?query=1');
344
+ expect(result).toContain('query=1');
345
+ });
346
+ });
347
+
348
+ describe('parseQuery', () => {
349
+ test('should parse simple query string', () => {
350
+ const result = UrlAndQueryString.parseQuery('?name=John&age=30');
351
+ expect(result).toEqual({ name: 'John', age: '30' });
352
+ });
353
+
354
+ test('should parse query string without question mark', () => {
355
+ const result = UrlAndQueryString.parseQuery('name=John&age=30');
356
+ expect(result).toEqual({ name: 'John', age: '30' });
357
+ });
358
+
359
+ test('should handle empty query string', () => {
360
+ const result = UrlAndQueryString.parseQuery('');
361
+ expect(result).toEqual({});
362
+ });
363
+
364
+ test('should handle parameter without value', () => {
365
+ const result = UrlAndQueryString.parseQuery('name=John&flag');
366
+ expect(result).toEqual({ name: 'John', flag: '' });
367
+ });
368
+
369
+ test('should handle encoded characters', () => {
370
+ const result = UrlAndQueryString.parseQuery('name=John%20Doe&message=hello%20world');
371
+ expect(result.name).toBe('John Doe');
372
+ expect(result.message).toBe('hello world');
373
+ });
374
+
375
+ test('should handle array parameters', () => {
376
+ const result = UrlAndQueryString.parseQuery('items[0]=apple&items[1]=banana');
377
+ expect(result.items).toEqual(['apple', 'banana']);
378
+ });
379
+
380
+ test('should handle nested array parameters', () => {
381
+ const result = UrlAndQueryString.parseQuery('data[user][name]=John&data[user][age]=30');
382
+ expect(result.data).toBeDefined();
383
+ expect(result.data.user).toBeDefined();
384
+ expect(result.data.user.name).toBe('John');
385
+ expect(result.data.user.age).toBe('30');
386
+ });
387
+ });
388
+
389
+ describe('buildQuery', () => {
390
+ test('should build query string from simple object', () => {
391
+ const result = UrlAndQueryString.buildQuery({ name: 'John', age: 30 });
392
+ expect(result).toContain('name=John');
393
+ expect(result).toContain('age=30');
394
+ });
395
+
396
+ test('should handle empty object', () => {
397
+ const result = UrlAndQueryString.buildQuery({});
398
+ expect(result).toBe('');
399
+ });
400
+
401
+ test('should handle boolean values', () => {
402
+ const result = UrlAndQueryString.buildQuery({ active: true, deleted: false });
403
+ expect(result).toContain('active=1');
404
+ expect(result).toContain('deleted=0');
405
+ });
406
+
407
+ test('should skip undefined values', () => {
408
+ const result = UrlAndQueryString.buildQuery({ name: 'John', age: undefined });
409
+ expect(result).toContain('name=John');
410
+ expect(result).not.toContain('undefined');
411
+ });
412
+
413
+ test('should skip null values', () => {
414
+ const result = UrlAndQueryString.buildQuery({ name: 'John', age: null });
415
+ expect(result).toContain('name=John');
416
+ expect(result).not.toContain('null');
417
+ });
418
+
419
+ test('should handle array values', () => {
420
+ const result = UrlAndQueryString.buildQuery({ items: ['apple', 'banana', 'orange'] });
421
+ expect(result).toContain('items[]=apple');
422
+ expect(result).toContain('items[]=banana');
423
+ expect(result).toContain('items[]=orange');
424
+ });
425
+
426
+ test('should handle nested objects', () => {
427
+ const result = UrlAndQueryString.buildQuery({ user: { name: 'John', age: 30 } });
428
+ expect(result).toContain('user[]=John');
429
+ expect(result).toContain('user[]=30');
430
+ });
431
+ });
432
+
433
+ describe('parseQueryString (deprecated)', () => {
434
+ test('should parse simple query string', () => {
435
+ const result = UrlAndQueryString.parseQueryString('?name=John&age=30');
436
+ expect(result).toEqual({ name: 'John', age: '30' });
437
+ });
438
+
439
+ test('should handle empty string', () => {
440
+ const result = UrlAndQueryString.parseQueryString('');
441
+ expect(result).toEqual({});
442
+ });
443
+
444
+ test('should handle null', () => {
445
+ const result = UrlAndQueryString.parseQueryString(null);
446
+ expect(result).toEqual({});
447
+ });
448
+
449
+ test('should parse boolean values', () => {
450
+ const result = UrlAndQueryString.parseQueryString('active=true&deleted=false');
451
+ expect(result.active).toBe(true);
452
+ expect(result.deleted).toBe(false);
453
+ });
454
+
455
+ test('should handle array parameters', () => {
456
+ const result = UrlAndQueryString.parseQueryString('items[]=apple&items[]=banana');
457
+ expect(result.items).toEqual(['apple', 'banana']);
458
+ });
459
+
460
+ test('should prevent prototype pollution with __proto__', () => {
461
+ const result = UrlAndQueryString.parseQueryString('__proto__[polluted]=true');
462
+ // Vérifie que la propriété polluted n'a pas été ajoutée au prototype
463
+ expect(result.polluted).toBeUndefined();
464
+ expect(Object.keys(result).length).toBe(0);
465
+ });
466
+ });
467
+
468
+ describe('getQuery (deprecated)', () => {
469
+ test('should get query string from URL', () => {
470
+ const result = UrlAndQueryString.getQuery('https://example.com/path?query=1&param=2');
471
+ expect(result).toBe('query=1&param=2');
472
+ });
473
+
474
+ test('should return empty string for URL without query', () => {
475
+ const result = UrlAndQueryString.getQuery('https://example.com/path');
476
+ expect(result).toBe('');
477
+ });
478
+
479
+ test('should handle URL with anchor', () => {
480
+ const result = UrlAndQueryString.getQuery('https://example.com/path?query=1#section');
481
+ expect(result).toBe('query=1');
482
+ });
483
+
484
+ test('should handle URL with only anchor', () => {
485
+ const result = UrlAndQueryString.getQuery('https://example.com/path#section');
486
+ expect(result).toBe('');
487
+ });
488
+ });
489
+ });