@osimatic/helpers-js 1.4.25 → 1.4.27

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 (111) hide show
  1. package/.claude/settings.local.json +1 -1
  2. package/duration.js +174 -125
  3. package/file.js +19 -4
  4. package/google_charts.js +2 -1
  5. package/location.js +5 -1
  6. package/media.js +6 -6
  7. package/multi_files_input.js +3 -1
  8. package/multiple_action_in_table.js +27 -11
  9. package/package.json +2 -1
  10. package/paging.js +2 -2
  11. package/tests/__mocks__/socket.io-client.js +13 -0
  12. package/tests/count_down.test.js +580 -0
  13. package/tests/details_sub_array.test.js +367 -0
  14. package/tests/file.test.js +210 -0
  15. package/tests/flash_message.test.js +297 -0
  16. package/tests/form_date.test.js +1142 -0
  17. package/tests/form_helper.test.js +780 -130
  18. package/tests/google_charts.test.js +768 -0
  19. package/tests/google_maps.test.js +655 -0
  20. package/tests/google_recaptcha.test.js +441 -0
  21. package/tests/import_from_csv.test.js +797 -0
  22. package/tests/list_box.test.js +255 -0
  23. package/tests/location.test.js +86 -0
  24. package/tests/media.test.js +15 -0
  25. package/tests/multi_files_input.test.js +1015 -0
  26. package/tests/multiple_action_in_table.test.js +477 -0
  27. package/tests/paging.test.js +646 -0
  28. package/tests/select_all.test.js +360 -0
  29. package/tests/sortable_list.test.js +602 -0
  30. package/tests/string.test.js +16 -0
  31. package/tests/web_rtc.test.js +458 -0
  32. package/tests/web_socket.test.js +538 -0
  33. package/tmpclaude-00a6-cwd +0 -1
  34. package/tmpclaude-0526-cwd +0 -1
  35. package/tmpclaude-0973-cwd +0 -1
  36. package/tmpclaude-0b61-cwd +0 -1
  37. package/tmpclaude-0fa4-cwd +0 -1
  38. package/tmpclaude-104f-cwd +0 -1
  39. package/tmpclaude-1468-cwd +0 -1
  40. package/tmpclaude-146f-cwd +0 -1
  41. package/tmpclaude-223d-cwd +0 -1
  42. package/tmpclaude-2330-cwd +0 -1
  43. package/tmpclaude-282a-cwd +0 -1
  44. package/tmpclaude-2846-cwd +0 -1
  45. package/tmpclaude-28a6-cwd +0 -1
  46. package/tmpclaude-2b5a-cwd +0 -1
  47. package/tmpclaude-2def-cwd +0 -1
  48. package/tmpclaude-324b-cwd +0 -1
  49. package/tmpclaude-35d3-cwd +0 -1
  50. package/tmpclaude-3906-cwd +0 -1
  51. package/tmpclaude-3b32-cwd +0 -1
  52. package/tmpclaude-3da9-cwd +0 -1
  53. package/tmpclaude-3dc3-cwd +0 -1
  54. package/tmpclaude-3e3b-cwd +0 -1
  55. package/tmpclaude-43b6-cwd +0 -1
  56. package/tmpclaude-4495-cwd +0 -1
  57. package/tmpclaude-462f-cwd +0 -1
  58. package/tmpclaude-4aa8-cwd +0 -1
  59. package/tmpclaude-4b29-cwd +0 -1
  60. package/tmpclaude-4db5-cwd +0 -1
  61. package/tmpclaude-4e01-cwd +0 -1
  62. package/tmpclaude-5101-cwd +0 -1
  63. package/tmpclaude-524f-cwd +0 -1
  64. package/tmpclaude-5636-cwd +0 -1
  65. package/tmpclaude-5cdd-cwd +0 -1
  66. package/tmpclaude-5f1f-cwd +0 -1
  67. package/tmpclaude-6078-cwd +0 -1
  68. package/tmpclaude-622e-cwd +0 -1
  69. package/tmpclaude-6802-cwd +0 -1
  70. package/tmpclaude-6e36-cwd +0 -1
  71. package/tmpclaude-7793-cwd +0 -1
  72. package/tmpclaude-7f96-cwd +0 -1
  73. package/tmpclaude-8566-cwd +0 -1
  74. package/tmpclaude-8874-cwd +0 -1
  75. package/tmpclaude-8915-cwd +0 -1
  76. package/tmpclaude-8c8b-cwd +0 -1
  77. package/tmpclaude-94df-cwd +0 -1
  78. package/tmpclaude-9859-cwd +0 -1
  79. package/tmpclaude-9ac5-cwd +0 -1
  80. package/tmpclaude-9f18-cwd +0 -1
  81. package/tmpclaude-a202-cwd +0 -1
  82. package/tmpclaude-a741-cwd +0 -1
  83. package/tmpclaude-ab5f-cwd +0 -1
  84. package/tmpclaude-b008-cwd +0 -1
  85. package/tmpclaude-b0a1-cwd +0 -1
  86. package/tmpclaude-b63d-cwd +0 -1
  87. package/tmpclaude-b681-cwd +0 -1
  88. package/tmpclaude-b72d-cwd +0 -1
  89. package/tmpclaude-b92f-cwd +0 -1
  90. package/tmpclaude-bc49-cwd +0 -1
  91. package/tmpclaude-bc50-cwd +0 -1
  92. package/tmpclaude-bccf-cwd +0 -1
  93. package/tmpclaude-be55-cwd +0 -1
  94. package/tmpclaude-c228-cwd +0 -1
  95. package/tmpclaude-c717-cwd +0 -1
  96. package/tmpclaude-c7ce-cwd +0 -1
  97. package/tmpclaude-cf3e-cwd +0 -1
  98. package/tmpclaude-d142-cwd +0 -1
  99. package/tmpclaude-d5bc-cwd +0 -1
  100. package/tmpclaude-d6ae-cwd +0 -1
  101. package/tmpclaude-d77a-cwd +0 -1
  102. package/tmpclaude-d8da-cwd +0 -1
  103. package/tmpclaude-dbdb-cwd +0 -1
  104. package/tmpclaude-de61-cwd +0 -1
  105. package/tmpclaude-de81-cwd +0 -1
  106. package/tmpclaude-df9d-cwd +0 -1
  107. package/tmpclaude-e786-cwd +0 -1
  108. package/tmpclaude-f01d-cwd +0 -1
  109. package/tmpclaude-f2a9-cwd +0 -1
  110. package/tmpclaude-fc36-cwd +0 -1
  111. package/tmpclaude-ffef-cwd +0 -1
@@ -0,0 +1,538 @@
1
+ // Mock socket.io-client before requiring WebSocket
2
+ jest.mock('socket.io-client');
3
+
4
+ const { WebSocket } = require('../web_socket');
5
+ const socketIoClient = require('socket.io-client');
6
+
7
+ describe('WebSocket', () => {
8
+ let mockEventBus;
9
+ let mockSocket;
10
+
11
+ beforeEach(() => {
12
+ // Reset the mock socket for each test
13
+ mockSocket = {
14
+ on: jest.fn(),
15
+ emit: jest.fn(),
16
+ connected: false
17
+ };
18
+
19
+ // Make io return our mock socket
20
+ socketIoClient.io.mockReturnValue(mockSocket);
21
+
22
+ // Mock EventBus
23
+ mockEventBus = {
24
+ publish: jest.fn(),
25
+ subscribe: jest.fn(),
26
+ unsubscribe: jest.fn()
27
+ };
28
+
29
+ // Mock EventBus module
30
+ jest.doMock('../event_bus', () => ({
31
+ EventBus: jest.fn(() => mockEventBus)
32
+ }));
33
+
34
+ // Clear static properties
35
+ delete WebSocket.eventBus;
36
+ delete WebSocket.socketConnectionErrors;
37
+ delete WebSocket.socketEvents;
38
+ delete WebSocket.busEvents;
39
+ delete WebSocket.customBusEvents;
40
+ delete WebSocket.logged;
41
+ delete WebSocket.instance;
42
+ });
43
+
44
+ afterEach(() => {
45
+ jest.clearAllMocks();
46
+ });
47
+
48
+ describe('setEventListeners', () => {
49
+ test('should set socket events', () => {
50
+ const socketEvents = ['message', 'update'];
51
+ const busEvents = ['send_message'];
52
+ const customBusEvents = [{ custom_name: 'custom_send', event_name: 'send' }];
53
+
54
+ WebSocket.setEventListeners(socketEvents, busEvents, customBusEvents);
55
+
56
+ expect(WebSocket.socketEvents).toBe(socketEvents);
57
+ });
58
+
59
+ test('should set bus events', () => {
60
+ const socketEvents = ['message'];
61
+ const busEvents = ['send_message', 'send_update'];
62
+ const customBusEvents = [];
63
+
64
+ WebSocket.setEventListeners(socketEvents, busEvents, customBusEvents);
65
+
66
+ expect(WebSocket.busEvents).toBe(busEvents);
67
+ });
68
+
69
+ test('should set custom bus events', () => {
70
+ const socketEvents = ['message'];
71
+ const busEvents = ['send_message'];
72
+ const customBusEvents = [
73
+ { custom_name: 'custom_send', event_name: 'send' },
74
+ { custom_name: 'custom_update', event_name: 'update' }
75
+ ];
76
+
77
+ WebSocket.setEventListeners(socketEvents, busEvents, customBusEvents);
78
+
79
+ expect(WebSocket.customBusEvents).toBe(customBusEvents);
80
+ });
81
+
82
+ test('should create EventBus instance', () => {
83
+ const socketEvents = [];
84
+ const busEvents = [];
85
+ const customBusEvents = [];
86
+
87
+ WebSocket.setEventListeners(socketEvents, busEvents, customBusEvents);
88
+
89
+ expect(WebSocket.eventBus).toBeDefined();
90
+ });
91
+
92
+ test('should set socket connection errors', () => {
93
+ const socketEvents = [];
94
+ const busEvents = [];
95
+ const customBusEvents = [];
96
+
97
+ WebSocket.setEventListeners(socketEvents, busEvents, customBusEvents);
98
+
99
+ expect(WebSocket.socketConnectionErrors).toEqual([
100
+ 'connect_error',
101
+ 'connect_timeout',
102
+ 'reconnect_error',
103
+ 'reconnect_failed'
104
+ ]);
105
+ });
106
+ });
107
+
108
+ describe('connect', () => {
109
+ beforeEach(() => {
110
+ WebSocket.setEventListeners(['message'], ['send'], [{ custom_name: 'custom_action', event_name: 'action' }]);
111
+ });
112
+
113
+ test('should create socket instance', () => {
114
+ const url = 'http://localhost:3000';
115
+ const options = { transports: ['websocket'] };
116
+
117
+ WebSocket.connect(url, options, {}, jest.fn(), jest.fn());
118
+
119
+ expect(socketIoClient.io).toHaveBeenCalledWith(url, options);
120
+ expect(WebSocket.instance).toBe(mockSocket);
121
+ });
122
+
123
+ test('should set logged to false', () => {
124
+ WebSocket.connect('http://localhost:3000', {}, {}, jest.fn(), jest.fn());
125
+
126
+ expect(WebSocket.logged).toBe(false);
127
+ });
128
+
129
+ test('should register error listeners', () => {
130
+ WebSocket.connect('http://localhost:3000', {}, {}, jest.fn(), jest.fn());
131
+
132
+ // Should register handlers for all error events
133
+ const eventNames = mockSocket.on.mock.calls.map(call => call[0]);
134
+ expect(eventNames).toContain('connect_error');
135
+ expect(eventNames).toContain('connect_timeout');
136
+ expect(eventNames).toContain('reconnect_error');
137
+ expect(eventNames).toContain('reconnect_failed');
138
+ expect(eventNames).toContain('error');
139
+ });
140
+
141
+ test('should register connect event listener', () => {
142
+ WebSocket.connect('http://localhost:3000', {}, {}, jest.fn(), jest.fn());
143
+
144
+ const eventNames = mockSocket.on.mock.calls.map(call => call[0]);
145
+ expect(eventNames).toContain('connect');
146
+ });
147
+
148
+ test('should register disconnect event listener', () => {
149
+ WebSocket.connect('http://localhost:3000', {}, {}, jest.fn(), jest.fn());
150
+
151
+ const eventNames = mockSocket.on.mock.calls.map(call => call[0]);
152
+ expect(eventNames).toContain('disconnect');
153
+ });
154
+
155
+ test('should register socket event listeners', () => {
156
+ WebSocket.connect('http://localhost:3000', {}, {}, jest.fn(), jest.fn());
157
+
158
+ const eventNames = mockSocket.on.mock.calls.map(call => call[0]);
159
+ expect(eventNames).toContain('message');
160
+ });
161
+ });
162
+
163
+ describe('registerErrorListeners', () => {
164
+ beforeEach(() => {
165
+ WebSocket.setEventListeners([], [], []);
166
+ WebSocket.instance = mockSocket;
167
+ });
168
+
169
+ test('should register handler for each connection error', () => {
170
+ const onUnavailableCallback = jest.fn();
171
+
172
+ WebSocket.registerErrorListeners(onUnavailableCallback);
173
+
174
+ expect(mockSocket.on).toHaveBeenCalledWith('connect_error', expect.any(Function));
175
+ expect(mockSocket.on).toHaveBeenCalledWith('connect_timeout', expect.any(Function));
176
+ expect(mockSocket.on).toHaveBeenCalledWith('reconnect_error', expect.any(Function));
177
+ expect(mockSocket.on).toHaveBeenCalledWith('reconnect_failed', expect.any(Function));
178
+ });
179
+
180
+ test('should register handler for error event', () => {
181
+ const onUnavailableCallback = jest.fn();
182
+
183
+ WebSocket.registerErrorListeners(onUnavailableCallback);
184
+
185
+ expect(mockSocket.on).toHaveBeenCalledWith('error', expect.any(Function));
186
+ });
187
+
188
+ test('should call clear when connection error occurs', () => {
189
+ const onUnavailableCallback = jest.fn();
190
+ const clearSpy = jest.spyOn(WebSocket, 'clear');
191
+
192
+ WebSocket.registerErrorListeners(onUnavailableCallback);
193
+
194
+ // Get the connect_error callback and trigger it
195
+ const errorCallback = mockSocket.on.mock.calls.find(call => call[0] === 'connect_error')[1];
196
+ errorCallback();
197
+
198
+ expect(clearSpy).toHaveBeenCalledWith(onUnavailableCallback, 'connect_error');
199
+
200
+ clearSpy.mockRestore();
201
+ });
202
+
203
+ test('should call clear with error when error event occurs', () => {
204
+ const onUnavailableCallback = jest.fn();
205
+ const clearSpy = jest.spyOn(WebSocket, 'clear');
206
+ const error = new Error('Connection failed');
207
+
208
+ WebSocket.registerErrorListeners(onUnavailableCallback);
209
+
210
+ // Get the error callback and trigger it
211
+ const errorCallback = mockSocket.on.mock.calls.find(call => call[0] === 'error')[1];
212
+ errorCallback(error);
213
+
214
+ expect(clearSpy).toHaveBeenCalledWith(onUnavailableCallback, error);
215
+
216
+ clearSpy.mockRestore();
217
+ });
218
+ });
219
+
220
+ describe('registerEventListeners', () => {
221
+ beforeEach(() => {
222
+ WebSocket.setEventListeners(['message'], ['send'], [{ custom_name: 'custom_action', event_name: 'action' }]);
223
+ WebSocket.instance = mockSocket;
224
+ });
225
+
226
+ test('should register connect handler', () => {
227
+ const connectInitPayload = { userId: '123' };
228
+ const onConnectionAckCallback = jest.fn();
229
+ const onUnavailableCallback = jest.fn();
230
+
231
+ WebSocket.registerEventListeners(connectInitPayload, onConnectionAckCallback, onUnavailableCallback);
232
+
233
+ expect(mockSocket.on).toHaveBeenCalledWith('connect', expect.any(Function));
234
+ });
235
+
236
+ test('should register disconnect handler', () => {
237
+ WebSocket.registerEventListeners({}, jest.fn(), jest.fn());
238
+
239
+ expect(mockSocket.on).toHaveBeenCalledWith('disconnect', expect.any(Function));
240
+ });
241
+
242
+ test('should emit connect_init on connect', () => {
243
+ const connectInitPayload = { userId: '123' };
244
+ const onConnectionAckCallback = jest.fn();
245
+
246
+ WebSocket.registerEventListeners(connectInitPayload, onConnectionAckCallback, jest.fn());
247
+
248
+ // Trigger connect
249
+ const connectCallback = mockSocket.on.mock.calls.find(call => call[0] === 'connect')[1];
250
+ connectCallback();
251
+
252
+ expect(WebSocket.logged).toBe(true);
253
+ expect(mockSocket.emit).toHaveBeenCalledWith('connect_init', connectInitPayload, onConnectionAckCallback);
254
+ });
255
+
256
+ test('should clear on reconnect', () => {
257
+ const clearSpy = jest.spyOn(WebSocket, 'clear');
258
+ WebSocket.logged = true;
259
+
260
+ WebSocket.registerEventListeners({}, jest.fn(), jest.fn());
261
+
262
+ // Trigger connect (reconnect scenario)
263
+ const connectCallback = mockSocket.on.mock.calls.find(call => call[0] === 'connect')[1];
264
+ connectCallback();
265
+
266
+ expect(clearSpy).toHaveBeenCalled();
267
+
268
+ clearSpy.mockRestore();
269
+ });
270
+
271
+ test('should register socket event handlers', () => {
272
+ WebSocket.registerEventListeners({}, jest.fn(), jest.fn());
273
+
274
+ expect(mockSocket.on).toHaveBeenCalledWith('message', expect.any(Function));
275
+ });
276
+
277
+ test('should publish socket events to event bus', () => {
278
+ WebSocket.registerEventListeners({}, jest.fn(), jest.fn());
279
+
280
+ // Trigger message event
281
+ const messageCallback = mockSocket.on.mock.calls.find(call => call[0] === 'message')[1];
282
+ const payload = { text: 'Hello' };
283
+ messageCallback(payload);
284
+
285
+ expect(mockEventBus.publish).toHaveBeenCalledWith('message', payload);
286
+ });
287
+
288
+ test('should subscribe to bus events', () => {
289
+ WebSocket.registerEventListeners({}, jest.fn(), jest.fn());
290
+
291
+ expect(mockEventBus.subscribe).toHaveBeenCalledWith('send', expect.any(Function));
292
+ });
293
+
294
+ test('should emit to socket when bus event received', () => {
295
+ WebSocket.registerEventListeners({}, jest.fn(), jest.fn());
296
+
297
+ // Get the bus event callback
298
+ const sendCallback = mockEventBus.subscribe.mock.calls.find(call => call[0] === 'send')[1];
299
+ const payload = { text: 'Hello' };
300
+ sendCallback(payload);
301
+
302
+ expect(mockSocket.emit).toHaveBeenCalledWith('send', payload);
303
+ });
304
+
305
+ test('should subscribe to custom bus events', () => {
306
+ WebSocket.registerEventListeners({}, jest.fn(), jest.fn());
307
+
308
+ expect(mockEventBus.subscribe).toHaveBeenCalledWith('custom_action', expect.any(Function));
309
+ });
310
+
311
+ test('should emit custom event name to socket', () => {
312
+ WebSocket.registerEventListeners({}, jest.fn(), jest.fn());
313
+
314
+ // Get the custom bus event callback
315
+ const customCallback = mockEventBus.subscribe.mock.calls.find(call => call[0] === 'custom_action')[1];
316
+ const payload = { data: 'test' };
317
+ customCallback(payload);
318
+
319
+ expect(mockSocket.emit).toHaveBeenCalledWith('action', payload);
320
+ });
321
+
322
+ test('should call clear on disconnect', () => {
323
+ const onUnavailableCallback = jest.fn();
324
+ const clearSpy = jest.spyOn(WebSocket, 'clear');
325
+
326
+ WebSocket.registerEventListeners({}, jest.fn(), onUnavailableCallback);
327
+
328
+ // Trigger disconnect
329
+ const disconnectCallback = mockSocket.on.mock.calls.find(call => call[0] === 'disconnect')[1];
330
+ disconnectCallback();
331
+
332
+ expect(clearSpy).toHaveBeenCalledWith(onUnavailableCallback);
333
+
334
+ clearSpy.mockRestore();
335
+ });
336
+ });
337
+
338
+ describe('unregisterEventListener', () => {
339
+ beforeEach(() => {
340
+ WebSocket.setEventListeners([], ['send', 'delete'], [{ custom_name: 'custom_send', event_name: 'send_custom' }]);
341
+ });
342
+
343
+ test('should unsubscribe all bus events', () => {
344
+ WebSocket.unregisterEventListener();
345
+
346
+ expect(mockEventBus.unsubscribe).toHaveBeenCalledWith('send', {});
347
+ expect(mockEventBus.unsubscribe).toHaveBeenCalledWith('delete', {});
348
+ });
349
+
350
+ test('should unsubscribe all custom bus events', () => {
351
+ WebSocket.unregisterEventListener();
352
+
353
+ expect(mockEventBus.unsubscribe).toHaveBeenCalledWith('custom_send', {});
354
+ });
355
+ });
356
+
357
+ describe('clear', () => {
358
+ beforeEach(() => {
359
+ WebSocket.setEventListeners([], ['send'], []);
360
+ });
361
+
362
+ test('should call unregisterEventListener', () => {
363
+ const unregisterSpy = jest.spyOn(WebSocket, 'unregisterEventListener');
364
+
365
+ WebSocket.clear();
366
+
367
+ expect(unregisterSpy).toHaveBeenCalled();
368
+
369
+ unregisterSpy.mockRestore();
370
+ });
371
+
372
+ test('should call onUnavailableCallback when provided', () => {
373
+ const onUnavailableCallback = jest.fn();
374
+ const error = 'connection_error';
375
+
376
+ WebSocket.clear(onUnavailableCallback, error);
377
+
378
+ expect(onUnavailableCallback).toHaveBeenCalledWith(error);
379
+ });
380
+
381
+ test('should not throw when onUnavailableCallback is undefined', () => {
382
+ expect(() => {
383
+ WebSocket.clear(undefined);
384
+ }).not.toThrow();
385
+ });
386
+
387
+ test('should pass error to callback', () => {
388
+ const onUnavailableCallback = jest.fn();
389
+ const error = new Error('Network error');
390
+
391
+ WebSocket.clear(onUnavailableCallback, error);
392
+
393
+ expect(onUnavailableCallback).toHaveBeenCalledWith(error);
394
+ });
395
+ });
396
+
397
+ describe('integration scenarios', () => {
398
+ beforeEach(() => {
399
+ WebSocket.setEventListeners(['message'], ['send'], [{ custom_name: 'custom_action', event_name: 'action' }]);
400
+ });
401
+
402
+ test('should complete full connection flow', () => {
403
+ const url = 'http://localhost:3000';
404
+ const options = { transports: ['websocket'] };
405
+ const connectInitPayload = { userId: '123' };
406
+ const onUnavailableCallback = jest.fn();
407
+ const onConnectionAckCallback = jest.fn();
408
+
409
+ WebSocket.connect(url, options, connectInitPayload, onUnavailableCallback, onConnectionAckCallback);
410
+
411
+ expect(WebSocket.instance).toBeDefined();
412
+ expect(WebSocket.logged).toBe(false);
413
+
414
+ // Trigger connect
415
+ const connectCallback = mockSocket.on.mock.calls.find(call => call[0] === 'connect')[1];
416
+ connectCallback();
417
+
418
+ expect(WebSocket.logged).toBe(true);
419
+ expect(mockSocket.emit).toHaveBeenCalledWith('connect_init', connectInitPayload, onConnectionAckCallback);
420
+ });
421
+
422
+ test('should handle error and cleanup', () => {
423
+ const url = 'http://localhost:3000';
424
+ const options = {};
425
+ const connectInitPayload = {};
426
+ const onUnavailableCallback = jest.fn();
427
+ const onConnectionAckCallback = jest.fn();
428
+
429
+ WebSocket.connect(url, options, connectInitPayload, onUnavailableCallback, onConnectionAckCallback);
430
+
431
+ // Trigger error
432
+ const errorCallback = mockSocket.on.mock.calls.find(call => call[0] === 'error')[1];
433
+ const error = new Error('Connection failed');
434
+ errorCallback(error);
435
+
436
+ expect(onUnavailableCallback).toHaveBeenCalledWith(error);
437
+ expect(mockEventBus.unsubscribe).toHaveBeenCalled();
438
+ });
439
+
440
+ test('should handle disconnect and cleanup', () => {
441
+ const url = 'http://localhost:3000';
442
+ const options = {};
443
+ const connectInitPayload = {};
444
+ const onUnavailableCallback = jest.fn();
445
+ const onConnectionAckCallback = jest.fn();
446
+
447
+ WebSocket.connect(url, options, connectInitPayload, onUnavailableCallback, onConnectionAckCallback);
448
+
449
+ // Trigger disconnect
450
+ const disconnectCallback = mockSocket.on.mock.calls.find(call => call[0] === 'disconnect')[1];
451
+ disconnectCallback();
452
+
453
+ expect(onUnavailableCallback).toHaveBeenCalled();
454
+ expect(mockEventBus.unsubscribe).toHaveBeenCalled();
455
+ });
456
+
457
+ test('should handle reconnect scenario', () => {
458
+ const url = 'http://localhost:3000';
459
+ const options = {};
460
+ const connectInitPayload = {};
461
+ const onUnavailableCallback = jest.fn();
462
+ const onConnectionAckCallback = jest.fn();
463
+
464
+ WebSocket.connect(url, options, connectInitPayload, onUnavailableCallback, onConnectionAckCallback);
465
+
466
+ // First connect
467
+ const connectCallback = mockSocket.on.mock.calls.find(call => call[0] === 'connect')[1];
468
+ connectCallback();
469
+ expect(WebSocket.logged).toBe(true);
470
+
471
+ jest.clearAllMocks();
472
+
473
+ // Reconnect (logged is already true)
474
+ connectCallback();
475
+
476
+ // Should have called clear() before reconnecting
477
+ expect(mockEventBus.unsubscribe).toHaveBeenCalled();
478
+ expect(WebSocket.logged).toBe(true);
479
+ });
480
+
481
+ test('should bridge socket events to event bus', () => {
482
+ WebSocket.connect('http://localhost:3000', {}, {}, jest.fn(), jest.fn());
483
+
484
+ // Trigger socket message event
485
+ const messageCallback = mockSocket.on.mock.calls.find(call => call[0] === 'message')[1];
486
+ const payload = { text: 'Hello from socket' };
487
+ messageCallback(payload);
488
+
489
+ expect(mockEventBus.publish).toHaveBeenCalledWith('message', payload);
490
+ });
491
+
492
+ test('should bridge bus events to socket', () => {
493
+ WebSocket.connect('http://localhost:3000', {}, {}, jest.fn(), jest.fn());
494
+
495
+ // Get bus event callback and trigger it
496
+ const sendCallback = mockEventBus.subscribe.mock.calls.find(call => call[0] === 'send')[1];
497
+ const payload = { text: 'Hello from bus' };
498
+ sendCallback(payload);
499
+
500
+ expect(mockSocket.emit).toHaveBeenCalledWith('send', payload);
501
+ });
502
+
503
+ test('should handle custom bus events correctly', () => {
504
+ WebSocket.connect('http://localhost:3000', {}, {}, jest.fn(), jest.fn());
505
+
506
+ // Get custom bus event callback
507
+ const customCallback = mockEventBus.subscribe.mock.calls.find(call => call[0] === 'custom_action')[1];
508
+ const payload = { data: 'custom data' };
509
+ customCallback(payload);
510
+
511
+ // Should emit with the mapped event name
512
+ expect(mockSocket.emit).toHaveBeenCalledWith('action', payload);
513
+ });
514
+
515
+ test('should handle all connection errors', () => {
516
+ const onUnavailableCallback = jest.fn();
517
+
518
+ WebSocket.connect('http://localhost:3000', {}, {}, onUnavailableCallback, jest.fn());
519
+
520
+ // Test each connection error type
521
+ const errors = ['connect_error', 'connect_timeout', 'reconnect_error', 'reconnect_failed'];
522
+
523
+ // Store all callbacks before clearing mocks
524
+ const errorCallbacks = errors.map(errorType => ({
525
+ type: errorType,
526
+ callback: mockSocket.on.mock.calls.find(call => call[0] === errorType)[1]
527
+ }));
528
+
529
+ errorCallbacks.forEach(({ type, callback }) => {
530
+ jest.clearAllMocks();
531
+ callback();
532
+
533
+ expect(onUnavailableCallback).toHaveBeenCalledWith(type);
534
+ expect(mockEventBus.unsubscribe).toHaveBeenCalled();
535
+ });
536
+ });
537
+ });
538
+ });
@@ -1 +0,0 @@
1
- /c/OSIMATIC/helpers-js
@@ -1 +0,0 @@
1
- /c/OSIMATIC/helpers-js
@@ -1 +0,0 @@
1
- /c/OSIMATIC/helpers-js
@@ -1 +0,0 @@
1
- /c/OSIMATIC/helpers-js
@@ -1 +0,0 @@
1
- /c/OSIMATIC/helpers-js
@@ -1 +0,0 @@
1
- /c/OSIMATIC/helpers-js
@@ -1 +0,0 @@
1
- /c/OSIMATIC/helpers-js
@@ -1 +0,0 @@
1
- /c/OSIMATIC/helpers-js
@@ -1 +0,0 @@
1
- /c/OSIMATIC/helpers-js
@@ -1 +0,0 @@
1
- /c/OSIMATIC/helpers-js
@@ -1 +0,0 @@
1
- /c/OSIMATIC/helpers-js
@@ -1 +0,0 @@
1
- /c/OSIMATIC/helpers-js
@@ -1 +0,0 @@
1
- /c/OSIMATIC/helpers-js
@@ -1 +0,0 @@
1
- /c/OSIMATIC/helpers-js
@@ -1 +0,0 @@
1
- /c/OSIMATIC/helpers-js
@@ -1 +0,0 @@
1
- /c/OSIMATIC/helpers-js
@@ -1 +0,0 @@
1
- /c/OSIMATIC/helpers-js
@@ -1 +0,0 @@
1
- /c/OSIMATIC/helpers-js
@@ -1 +0,0 @@
1
- /c/OSIMATIC/helpers-js
@@ -1 +0,0 @@
1
- /c/OSIMATIC/helpers-js
@@ -1 +0,0 @@
1
- /c/OSIMATIC/helpers-js
@@ -1 +0,0 @@
1
- /c/OSIMATIC/helpers-js
@@ -1 +0,0 @@
1
- /c/OSIMATIC/helpers-js
@@ -1 +0,0 @@
1
- /c/OSIMATIC/helpers-js
@@ -1 +0,0 @@
1
- /c/OSIMATIC/helpers-js
@@ -1 +0,0 @@
1
- /c/OSIMATIC/helpers-js
@@ -1 +0,0 @@
1
- /c/OSIMATIC/helpers-js
@@ -1 +0,0 @@
1
- /c/OSIMATIC/helpers-js
@@ -1 +0,0 @@
1
- /c/OSIMATIC/helpers-js
@@ -1 +0,0 @@
1
- /c/OSIMATIC/helpers-js
@@ -1 +0,0 @@
1
- /c/OSIMATIC/helpers-js
@@ -1 +0,0 @@
1
- /c/OSIMATIC/helpers-js
@@ -1 +0,0 @@
1
- /c/OSIMATIC/helpers-js
@@ -1 +0,0 @@
1
- /c/OSIMATIC/helpers-js
@@ -1 +0,0 @@
1
- /c/OSIMATIC/helpers-js
@@ -1 +0,0 @@
1
- /c/OSIMATIC/helpers-js
@@ -1 +0,0 @@
1
- /c/OSIMATIC/helpers-js
@@ -1 +0,0 @@
1
- /c/OSIMATIC/helpers-js
@@ -1 +0,0 @@
1
- /c/OSIMATIC/helpers-js
@@ -1 +0,0 @@
1
- /c/OSIMATIC/helpers-js
@@ -1 +0,0 @@
1
- /c/OSIMATIC/helpers-js
@@ -1 +0,0 @@
1
- /c/OSIMATIC/helpers-js