cojson-transport-ws 0.8.13 → 0.8.17

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.
@@ -1,466 +1,459 @@
1
- import { describe, test, expect, vi, Mocked } from "vitest";
2
- import {
3
- BUFFER_LIMIT,
4
- BUFFER_LIMIT_POLLING_INTERVAL,
5
- createWebSocketPeer,
6
- CreateWebSocketPeerOpts,
7
- } from "../index.js";
8
- import { AnyWebSocket } from "../types.js";
9
1
  import { SyncMessage } from "cojson";
10
2
  import { Channel } from "cojson/src/streamUtils.ts";
3
+ import { Mocked, describe, expect, test, vi } from "vitest";
11
4
  import { MAX_OUTGOING_MESSAGES_CHUNK_BYTES } from "../BatchedOutgoingMessages.js";
5
+ import {
6
+ BUFFER_LIMIT,
7
+ BUFFER_LIMIT_POLLING_INTERVAL,
8
+ CreateWebSocketPeerOpts,
9
+ createWebSocketPeer,
10
+ } from "../index.js";
11
+ import { AnyWebSocket } from "../types.js";
12
12
 
13
13
  function setup(opts: Partial<CreateWebSocketPeerOpts> = {}) {
14
- const listeners = new Map<string, (event: MessageEvent) => void>();
15
-
16
- const mockWebSocket = {
17
- readyState: 1,
18
- addEventListener: vi.fn().mockImplementation((type, listener) => {
19
- listeners.set(type, listener);
20
- }),
21
- removeEventListener: vi.fn().mockImplementation((type) => {
22
- listeners.delete(type);
23
- }),
24
- close: vi.fn(),
25
- send: vi.fn(),
26
- } as unknown as Mocked<AnyWebSocket>;
27
-
28
- const peer = createWebSocketPeer({
29
- id: "test-peer",
30
- websocket: mockWebSocket,
31
- role: "client",
32
- batchingByDefault: true,
33
- ...opts,
34
- });
35
-
36
- return { mockWebSocket, peer, listeners };
14
+ const listeners = new Map<string, (event: MessageEvent) => void>();
15
+
16
+ const mockWebSocket = {
17
+ readyState: 1,
18
+ addEventListener: vi.fn().mockImplementation((type, listener) => {
19
+ listeners.set(type, listener);
20
+ }),
21
+ removeEventListener: vi.fn().mockImplementation((type) => {
22
+ listeners.delete(type);
23
+ }),
24
+ close: vi.fn(),
25
+ send: vi.fn(),
26
+ } as unknown as Mocked<AnyWebSocket>;
27
+
28
+ const peer = createWebSocketPeer({
29
+ id: "test-peer",
30
+ websocket: mockWebSocket,
31
+ role: "client",
32
+ batchingByDefault: true,
33
+ ...opts,
34
+ });
35
+
36
+ return { mockWebSocket, peer, listeners };
37
37
  }
38
38
 
39
39
  function serializeMessages(messages: SyncMessage[]) {
40
- return messages.map((msg) => JSON.stringify(msg)).join("\n");
40
+ return messages.map((msg) => JSON.stringify(msg)).join("\n");
41
41
  }
42
42
 
43
43
  describe("createWebSocketPeer", () => {
44
- test("should create a peer with correct properties", () => {
45
- const { peer } = setup();
46
-
47
- expect(peer).toHaveProperty("id", "test-peer");
48
- expect(peer).toHaveProperty("incoming");
49
- expect(peer).toHaveProperty("outgoing");
50
- expect(peer).toHaveProperty("role", "client");
51
- expect(peer).toHaveProperty("crashOnClose", false);
44
+ test("should create a peer with correct properties", () => {
45
+ const { peer } = setup();
46
+
47
+ expect(peer).toHaveProperty("id", "test-peer");
48
+ expect(peer).toHaveProperty("incoming");
49
+ expect(peer).toHaveProperty("outgoing");
50
+ expect(peer).toHaveProperty("role", "client");
51
+ expect(peer).toHaveProperty("crashOnClose", false);
52
+ });
53
+
54
+ test("should handle disconnection", async () => {
55
+ expect.assertions(1);
56
+
57
+ const { listeners, peer } = setup();
58
+
59
+ const incoming = peer.incoming as Channel<
60
+ SyncMessage | "Disconnected" | "PingTimeout"
61
+ >;
62
+ const pushSpy = vi.spyOn(incoming, "push");
63
+
64
+ const closeHandler = listeners.get("close");
65
+
66
+ closeHandler?.(new MessageEvent("close"));
67
+
68
+ expect(pushSpy).toHaveBeenCalledWith("Disconnected");
69
+ });
70
+
71
+ test("should handle ping timeout", async () => {
72
+ vi.useFakeTimers();
73
+ const { listeners, peer } = setup();
74
+
75
+ const incoming = peer.incoming as Channel<
76
+ SyncMessage | "Disconnected" | "PingTimeout"
77
+ >;
78
+ const pushSpy = vi.spyOn(incoming, "push");
79
+
80
+ const messageHandler = listeners.get("message");
81
+
82
+ messageHandler?.(new MessageEvent("message", { data: "{}" }));
83
+
84
+ await vi.advanceTimersByTimeAsync(10_000);
85
+
86
+ expect(pushSpy).toHaveBeenCalledWith("PingTimeout");
87
+
88
+ vi.useRealTimers();
89
+ });
90
+
91
+ test("should send outgoing messages", async () => {
92
+ const { peer, mockWebSocket } = setup();
93
+
94
+ const testMessage: SyncMessage = {
95
+ action: "known",
96
+ id: "co_ztest",
97
+ header: false,
98
+ sessions: {},
99
+ };
100
+ const promise = peer.outgoing.push(testMessage);
101
+
102
+ await waitFor(() => {
103
+ expect(mockWebSocket.send).toHaveBeenCalledWith(
104
+ JSON.stringify(testMessage),
105
+ );
52
106
  });
53
107
 
54
- test("should handle disconnection", async () => {
55
- expect.assertions(1);
108
+ await expect(promise).resolves.toBeUndefined();
109
+ });
110
+
111
+ test("should stop sending messages when the websocket is closed", async () => {
112
+ const { peer, mockWebSocket } = setup();
56
113
 
57
- const { listeners, peer } = setup();
114
+ mockWebSocket.send.mockImplementation(() => {
115
+ mockWebSocket.readyState = 0;
116
+ });
58
117
 
59
- const incoming = peer.incoming as Channel<
60
- SyncMessage | "Disconnected" | "PingTimeout"
61
- >;
62
- const pushSpy = vi.spyOn(incoming, "push");
118
+ const message1: SyncMessage = {
119
+ action: "known",
120
+ id: "co_ztest",
121
+ header: false,
122
+ sessions: {},
123
+ };
63
124
 
64
- const closeHandler = listeners.get("close");
125
+ const message2: SyncMessage = {
126
+ action: "content",
127
+ id: "co_zlow",
128
+ new: {},
129
+ priority: 1,
130
+ };
65
131
 
66
- closeHandler?.(new MessageEvent("close"));
132
+ void peer.outgoing.push(message1);
67
133
 
68
- expect(pushSpy).toHaveBeenCalledWith("Disconnected");
134
+ await waitFor(() => {
135
+ expect(mockWebSocket.send).toHaveBeenCalled();
69
136
  });
70
137
 
71
- test("should handle ping timeout", async () => {
72
- vi.useFakeTimers();
73
- const { listeners, peer } = setup();
138
+ expect(mockWebSocket.send).toHaveBeenCalledWith(JSON.stringify(message1));
139
+
140
+ mockWebSocket.send.mockClear();
141
+ void peer.outgoing.push(message2);
142
+
143
+ await new Promise<void>((resolve) => setTimeout(resolve, 100));
144
+
145
+ expect(mockWebSocket.send).not.toHaveBeenCalled();
146
+ });
147
+
148
+ test("should close the websocket connection", () => {
149
+ const { mockWebSocket, peer } = setup();
74
150
 
75
- const incoming = peer.incoming as Channel<
76
- SyncMessage | "Disconnected" | "PingTimeout"
77
- >;
78
- const pushSpy = vi.spyOn(incoming, "push");
151
+ peer.outgoing.close();
79
152
 
80
- const messageHandler = listeners.get("message");
153
+ expect(mockWebSocket.close).toHaveBeenCalled();
154
+ });
81
155
 
82
- messageHandler?.(new MessageEvent("message", { data: "{}" }));
156
+ describe("batchingByDefault = true", () => {
157
+ test("should batch outgoing messages", async () => {
158
+ const { peer, mockWebSocket } = setup();
83
159
 
84
- await vi.advanceTimersByTimeAsync(10_000);
160
+ mockWebSocket.send.mockImplementation(() => {
161
+ mockWebSocket.readyState = 0;
162
+ });
85
163
 
86
- expect(pushSpy).toHaveBeenCalledWith("PingTimeout");
164
+ const message1: SyncMessage = {
165
+ action: "known",
166
+ id: "co_ztest",
167
+ header: false,
168
+ sessions: {},
169
+ };
87
170
 
88
- vi.useRealTimers();
171
+ const message2: SyncMessage = {
172
+ action: "content",
173
+ id: "co_zlow",
174
+ new: {},
175
+ priority: 1,
176
+ };
177
+
178
+ void peer.outgoing.push(message1);
179
+ void peer.outgoing.push(message2);
180
+
181
+ await waitFor(() => {
182
+ expect(mockWebSocket.send).toHaveBeenCalled();
183
+ });
184
+
185
+ expect(mockWebSocket.send).toHaveBeenCalledWith(
186
+ [message1, message2].map((msg) => JSON.stringify(msg)).join("\n"),
187
+ );
89
188
  });
90
189
 
91
- test("should send outgoing messages", async () => {
92
- const { peer, mockWebSocket } = setup();
190
+ test("should send all the pending messages when the websocket is closed", async () => {
191
+ const { peer, mockWebSocket } = setup();
93
192
 
94
- const testMessage: SyncMessage = {
95
- action: "known",
96
- id: "co_ztest",
97
- header: false,
98
- sessions: {},
99
- };
100
- const promise = peer.outgoing.push(testMessage);
193
+ const message1: SyncMessage = {
194
+ action: "known",
195
+ id: "co_ztest",
196
+ header: false,
197
+ sessions: {},
198
+ };
101
199
 
102
- await waitFor(() => {
103
- expect(mockWebSocket.send).toHaveBeenCalledWith(
104
- JSON.stringify(testMessage),
105
- );
106
- });
200
+ const message2: SyncMessage = {
201
+ action: "content",
202
+ id: "co_zlow",
203
+ new: {},
204
+ priority: 1,
205
+ };
107
206
 
108
- await expect(promise).resolves.toBeUndefined();
207
+ void peer.outgoing.push(message1);
208
+ void peer.outgoing.push(message2);
209
+
210
+ peer.outgoing.close();
211
+
212
+ expect(mockWebSocket.send).toHaveBeenCalledWith(
213
+ [message1, message2].map((msg) => JSON.stringify(msg)).join("\n"),
214
+ );
109
215
  });
110
216
 
111
- test("should stop sending messages when the websocket is closed", async () => {
112
- const { peer, mockWebSocket } = setup();
217
+ test("should limit the chunk size to MAX_OUTGOING_MESSAGES_CHUNK_SIZE", async () => {
218
+ const { peer, mockWebSocket } = setup();
219
+
220
+ const message1: SyncMessage = {
221
+ action: "known",
222
+ id: "co_ztest",
223
+ header: false,
224
+ sessions: {},
225
+ };
226
+ const message2: SyncMessage = {
227
+ action: "content",
228
+ id: "co_zlow",
229
+ new: {},
230
+ priority: 1,
231
+ };
232
+
233
+ const stream: SyncMessage[] = [];
234
+
235
+ while (
236
+ serializeMessages(stream.concat(message1)).length <
237
+ MAX_OUTGOING_MESSAGES_CHUNK_BYTES
238
+ ) {
239
+ stream.push(message1);
240
+ void peer.outgoing.push(message1);
241
+ }
242
+
243
+ void peer.outgoing.push(message2);
113
244
 
114
- mockWebSocket.send.mockImplementation(() => {
115
- mockWebSocket.readyState = 0;
116
- });
245
+ await waitFor(() => {
246
+ expect(mockWebSocket.send).toHaveBeenCalledTimes(2);
247
+ });
117
248
 
118
- const message1: SyncMessage = {
119
- action: "known",
120
- id: "co_ztest",
121
- header: false,
122
- sessions: {},
123
- };
249
+ expect(mockWebSocket.send).toHaveBeenCalledWith(
250
+ serializeMessages(stream),
251
+ );
124
252
 
125
- const message2: SyncMessage = {
126
- action: "content",
127
- id: "co_zlow",
128
- new: {},
129
- priority: 1,
130
- };
253
+ expect(mockWebSocket.send).toHaveBeenNthCalledWith(
254
+ 2,
255
+ JSON.stringify(message2),
256
+ );
257
+ });
131
258
 
259
+ test("should wait for the buffer to be under BUFFER_LIMIT before sending more messages", async () => {
260
+ vi.useFakeTimers();
261
+ const { peer, mockWebSocket } = setup();
262
+
263
+ mockWebSocket.send.mockImplementation(() => {
264
+ mockWebSocket.bufferedAmount = BUFFER_LIMIT + 1;
265
+ });
266
+
267
+ const message1: SyncMessage = {
268
+ action: "known",
269
+ id: "co_ztest",
270
+ header: false,
271
+ sessions: {},
272
+ };
273
+ const message2: SyncMessage = {
274
+ action: "content",
275
+ id: "co_zlow",
276
+ new: {},
277
+ priority: 1,
278
+ };
279
+
280
+ const stream: SyncMessage[] = [];
281
+
282
+ while (
283
+ serializeMessages(stream.concat(message1)).length <
284
+ MAX_OUTGOING_MESSAGES_CHUNK_BYTES
285
+ ) {
286
+ stream.push(message1);
132
287
  void peer.outgoing.push(message1);
288
+ }
289
+
290
+ void peer.outgoing.push(message2);
291
+
292
+ await vi.advanceTimersByTimeAsync(100);
133
293
 
134
- await waitFor(() => {
135
- expect(mockWebSocket.send).toHaveBeenCalled();
136
- });
294
+ expect(mockWebSocket.send).toHaveBeenCalledWith(
295
+ serializeMessages(stream),
296
+ );
137
297
 
138
- expect(mockWebSocket.send).toHaveBeenCalledWith(JSON.stringify(message1));
298
+ mockWebSocket.bufferedAmount = 0;
139
299
 
140
- mockWebSocket.send.mockClear();
141
- void peer.outgoing.push(message2);
300
+ await vi.advanceTimersByTimeAsync(BUFFER_LIMIT_POLLING_INTERVAL + 1);
142
301
 
143
- await new Promise<void>((resolve) => setTimeout(resolve, 100))
302
+ expect(mockWebSocket.send).toHaveBeenNthCalledWith(
303
+ 2,
304
+ JSON.stringify(message2),
305
+ );
144
306
 
145
- expect(mockWebSocket.send).not.toHaveBeenCalled();
307
+ vi.useRealTimers();
308
+ });
309
+ });
310
+
311
+ describe("batchingByDefault = false", () => {
312
+ test("should not batch outgoing messages", async () => {
313
+ const { peer, mockWebSocket } = setup({ batchingByDefault: false });
314
+
315
+ const message1: SyncMessage = {
316
+ action: "known",
317
+ id: "co_ztest",
318
+ header: false,
319
+ sessions: {},
320
+ };
321
+
322
+ const message2: SyncMessage = {
323
+ action: "content",
324
+ id: "co_zlow",
325
+ new: {},
326
+ priority: 1,
327
+ };
328
+
329
+ void peer.outgoing.push(message1);
330
+ void peer.outgoing.push(message2);
331
+
332
+ await waitFor(() => {
333
+ expect(mockWebSocket.send).toHaveBeenCalled();
334
+ });
335
+
336
+ expect(mockWebSocket.send).toHaveBeenNthCalledWith(
337
+ 1,
338
+ JSON.stringify(message1),
339
+ );
340
+ expect(mockWebSocket.send).toHaveBeenNthCalledWith(
341
+ 2,
342
+ JSON.stringify(message2),
343
+ );
146
344
  });
147
345
 
148
- test("should close the websocket connection", () => {
149
- const { mockWebSocket, peer } = setup();
346
+ test("should start batching outgoing messages when reiceving a batched message", async () => {
347
+ const { peer, mockWebSocket, listeners } = setup({
348
+ batchingByDefault: false,
349
+ });
350
+
351
+ const message1: SyncMessage = {
352
+ action: "known",
353
+ id: "co_ztest",
354
+ header: false,
355
+ sessions: {},
356
+ };
357
+
358
+ const messageHandler = listeners.get("message");
359
+
360
+ messageHandler?.(
361
+ new MessageEvent("message", {
362
+ data: Array.from({ length: 5 }, () => message1)
363
+ .map((msg) => JSON.stringify(msg))
364
+ .join("\n"),
365
+ }),
366
+ );
150
367
 
151
- peer.outgoing.close();
368
+ const message2: SyncMessage = {
369
+ action: "content",
370
+ id: "co_zlow",
371
+ new: {},
372
+ priority: 1,
373
+ };
152
374
 
153
- expect(mockWebSocket.close).toHaveBeenCalled();
154
- });
375
+ void peer.outgoing.push(message1);
376
+ void peer.outgoing.push(message2);
155
377
 
156
- describe("batchingByDefault = true", () => {
157
- test("should batch outgoing messages", async () => {
158
- const { peer, mockWebSocket } = setup();
159
-
160
- mockWebSocket.send.mockImplementation(() => {
161
- mockWebSocket.readyState = 0;
162
- });
163
-
164
- const message1: SyncMessage = {
165
- action: "known",
166
- id: "co_ztest",
167
- header: false,
168
- sessions: {},
169
- };
170
-
171
- const message2: SyncMessage = {
172
- action: "content",
173
- id: "co_zlow",
174
- new: {},
175
- priority: 1,
176
- };
177
-
178
- void peer.outgoing.push(message1);
179
- void peer.outgoing.push(message2);
180
-
181
- await waitFor(() => {
182
- expect(mockWebSocket.send).toHaveBeenCalled();
183
- });
184
-
185
- expect(mockWebSocket.send).toHaveBeenCalledWith(
186
- [message1, message2]
187
- .map((msg) => JSON.stringify(msg))
188
- .join("\n"),
189
- );
190
- });
191
-
192
- test("should send all the pending messages when the websocket is closed", async () => {
193
- const { peer, mockWebSocket } = setup();
194
-
195
- const message1: SyncMessage = {
196
- action: "known",
197
- id: "co_ztest",
198
- header: false,
199
- sessions: {},
200
- };
201
-
202
- const message2: SyncMessage = {
203
- action: "content",
204
- id: "co_zlow",
205
- new: {},
206
- priority: 1,
207
- };
208
-
209
- void peer.outgoing.push(message1);
210
- void peer.outgoing.push(message2);
211
-
212
- peer.outgoing.close();
213
-
214
- expect(mockWebSocket.send).toHaveBeenCalledWith(
215
- [message1, message2]
216
- .map((msg) => JSON.stringify(msg))
217
- .join("\n"),
218
- );
219
- });
220
-
221
- test("should limit the chunk size to MAX_OUTGOING_MESSAGES_CHUNK_SIZE", async () => {
222
- const { peer, mockWebSocket } = setup();
223
-
224
- const message1: SyncMessage = {
225
- action: "known",
226
- id: "co_ztest",
227
- header: false,
228
- sessions: {},
229
- };
230
- const message2: SyncMessage = {
231
- action: "content",
232
- id: "co_zlow",
233
- new: {},
234
- priority: 1,
235
- };
236
-
237
- const stream: SyncMessage[] = [];
238
-
239
- while (serializeMessages(stream.concat(message1)).length < MAX_OUTGOING_MESSAGES_CHUNK_BYTES) {
240
- stream.push(message1);
241
- void peer.outgoing.push(message1);
242
- }
243
-
244
- void peer.outgoing.push(message2);
245
-
246
- await waitFor(() => {
247
- expect(mockWebSocket.send).toHaveBeenCalledTimes(2);
248
- });
249
-
250
- expect(mockWebSocket.send).toHaveBeenCalledWith(
251
- serializeMessages(stream),
252
- );
253
-
254
- expect(mockWebSocket.send).toHaveBeenNthCalledWith(
255
- 2,
256
- JSON.stringify(message2),
257
- );
258
- });
259
-
260
- test("should wait for the buffer to be under BUFFER_LIMIT before sending more messages", async () => {
261
- vi.useFakeTimers();
262
- const { peer, mockWebSocket } = setup();
263
-
264
- mockWebSocket.send.mockImplementation(() => {
265
- mockWebSocket.bufferedAmount = BUFFER_LIMIT + 1;
266
- });
267
-
268
- const message1: SyncMessage = {
269
- action: "known",
270
- id: "co_ztest",
271
- header: false,
272
- sessions: {},
273
- };
274
- const message2: SyncMessage = {
275
- action: "content",
276
- id: "co_zlow",
277
- new: {},
278
- priority: 1,
279
- };
280
-
281
- const stream: SyncMessage[] = [];
282
-
283
- while (serializeMessages(stream.concat(message1)).length < MAX_OUTGOING_MESSAGES_CHUNK_BYTES) {
284
- stream.push(message1);
285
- void peer.outgoing.push(message1);
286
- }
287
-
288
- void peer.outgoing.push(message2);
289
-
290
- await vi.advanceTimersByTimeAsync(100);
291
-
292
- expect(mockWebSocket.send).toHaveBeenCalledWith(
293
- serializeMessages(stream),
294
- );
295
-
296
- mockWebSocket.bufferedAmount = 0;
297
-
298
- await vi.advanceTimersByTimeAsync(
299
- BUFFER_LIMIT_POLLING_INTERVAL + 1,
300
- );
301
-
302
- expect(mockWebSocket.send).toHaveBeenNthCalledWith(
303
- 2,
304
- JSON.stringify(message2),
305
- );
306
-
307
- vi.useRealTimers();
308
- });
378
+ await waitFor(() => {
379
+ expect(mockWebSocket.send).toHaveBeenCalled();
380
+ });
381
+
382
+ expect(mockWebSocket.send).toHaveBeenCalledWith(
383
+ [message1, message2].map((msg) => JSON.stringify(msg)).join("\n"),
384
+ );
309
385
  });
310
386
 
311
- describe("batchingByDefault = false", () => {
312
- test("should not batch outgoing messages", async () => {
313
- const { peer, mockWebSocket } = setup({ batchingByDefault: false });
314
-
315
- const message1: SyncMessage = {
316
- action: "known",
317
- id: "co_ztest",
318
- header: false,
319
- sessions: {},
320
- };
321
-
322
- const message2: SyncMessage = {
323
- action: "content",
324
- id: "co_zlow",
325
- new: {},
326
- priority: 1,
327
- };
328
-
329
- void peer.outgoing.push(message1);
330
- void peer.outgoing.push(message2);
331
-
332
- await waitFor(() => {
333
- expect(mockWebSocket.send).toHaveBeenCalled();
334
- });
335
-
336
- expect(mockWebSocket.send).toHaveBeenNthCalledWith(
337
- 1,
338
- JSON.stringify(message1),
339
- );
340
- expect(mockWebSocket.send).toHaveBeenNthCalledWith(
341
- 2,
342
- JSON.stringify(message2),
343
- );
344
- });
345
-
346
- test("should start batching outgoing messages when reiceving a batched message", async () => {
347
- const { peer, mockWebSocket, listeners } = setup({
348
- batchingByDefault: false,
349
- });
350
-
351
- const message1: SyncMessage = {
352
- action: "known",
353
- id: "co_ztest",
354
- header: false,
355
- sessions: {},
356
- };
357
-
358
- const messageHandler = listeners.get("message");
359
-
360
- messageHandler?.(
361
- new MessageEvent("message", {
362
- data: Array.from(
363
- { length: 5 },
364
- () => message1,
365
- )
366
- .map((msg) => JSON.stringify(msg))
367
- .join("\n"),
368
- }),
369
- );
370
-
371
-
372
- const message2: SyncMessage = {
373
- action: "content",
374
- id: "co_zlow",
375
- new: {},
376
- priority: 1,
377
- };
378
-
379
- void peer.outgoing.push(message1);
380
- void peer.outgoing.push(message2);
381
-
382
- await waitFor(() => {
383
- expect(mockWebSocket.send).toHaveBeenCalled();
384
- });
385
-
386
- expect(mockWebSocket.send).toHaveBeenCalledWith(
387
- [message1, message2]
388
- .map((msg) => JSON.stringify(msg))
389
- .join("\n"),
390
- );
391
- });
392
-
393
- test("should not start batching outgoing messages when reiceving non-batched message", async () => {
394
- const { peer, mockWebSocket, listeners } = setup({
395
- batchingByDefault: false,
396
- });
397
-
398
- const message1: SyncMessage = {
399
- action: "known",
400
- id: "co_ztest",
401
- header: false,
402
- sessions: {},
403
- };
404
-
405
- const messageHandler = listeners.get("message");
406
-
407
- messageHandler?.(
408
- new MessageEvent("message", {
409
- data: JSON.stringify(message1),
410
- }),
411
- );
412
-
413
-
414
- const message2: SyncMessage = {
415
- action: "content",
416
- id: "co_zlow",
417
- new: {},
418
- priority: 1,
419
- };
420
-
421
- void peer.outgoing.push(message1);
422
- void peer.outgoing.push(message2);
423
-
424
- await waitFor(() => {
425
- expect(mockWebSocket.send).toHaveBeenCalled();
426
- });
427
-
428
- expect(mockWebSocket.send).toHaveBeenNthCalledWith(
429
- 1,
430
- JSON.stringify(message1),
431
- );
432
- expect(mockWebSocket.send).toHaveBeenNthCalledWith(
433
- 2,
434
- JSON.stringify(message2),
435
- );
436
- });
387
+ test("should not start batching outgoing messages when reiceving non-batched message", async () => {
388
+ const { peer, mockWebSocket, listeners } = setup({
389
+ batchingByDefault: false,
390
+ });
391
+
392
+ const message1: SyncMessage = {
393
+ action: "known",
394
+ id: "co_ztest",
395
+ header: false,
396
+ sessions: {},
397
+ };
398
+
399
+ const messageHandler = listeners.get("message");
400
+
401
+ messageHandler?.(
402
+ new MessageEvent("message", {
403
+ data: JSON.stringify(message1),
404
+ }),
405
+ );
406
+
407
+ const message2: SyncMessage = {
408
+ action: "content",
409
+ id: "co_zlow",
410
+ new: {},
411
+ priority: 1,
412
+ };
413
+
414
+ void peer.outgoing.push(message1);
415
+ void peer.outgoing.push(message2);
416
+
417
+ await waitFor(() => {
418
+ expect(mockWebSocket.send).toHaveBeenCalled();
419
+ });
420
+
421
+ expect(mockWebSocket.send).toHaveBeenNthCalledWith(
422
+ 1,
423
+ JSON.stringify(message1),
424
+ );
425
+ expect(mockWebSocket.send).toHaveBeenNthCalledWith(
426
+ 2,
427
+ JSON.stringify(message2),
428
+ );
437
429
  });
430
+ });
438
431
  });
439
432
 
440
433
  function waitFor(callback: () => boolean | void) {
441
- return new Promise<void>((resolve, reject) => {
442
- const checkPassed = () => {
443
- try {
444
- return { ok: callback(), error: null };
445
- } catch (error) {
446
- return { ok: false, error };
447
- }
448
- };
449
-
450
- let retries = 0;
451
-
452
- const interval = setInterval(() => {
453
- const { ok, error } = checkPassed();
454
-
455
- if (ok !== false) {
456
- clearInterval(interval);
457
- resolve();
458
- }
459
-
460
- if (++retries > 10) {
461
- clearInterval(interval);
462
- reject(error);
463
- }
464
- }, 100);
465
- });
434
+ return new Promise<void>((resolve, reject) => {
435
+ const checkPassed = () => {
436
+ try {
437
+ return { ok: callback(), error: null };
438
+ } catch (error) {
439
+ return { ok: false, error };
440
+ }
441
+ };
442
+
443
+ let retries = 0;
444
+
445
+ const interval = setInterval(() => {
446
+ const { ok, error } = checkPassed();
447
+
448
+ if (ok !== false) {
449
+ clearInterval(interval);
450
+ resolve();
451
+ }
452
+
453
+ if (++retries > 10) {
454
+ clearInterval(interval);
455
+ reject(error);
456
+ }
457
+ }, 100);
458
+ });
466
459
  }