@fluid-internal/presence-runtime 2.101.1 → 2.103.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.
Files changed (85) hide show
  1. package/dist/packageVersion.d.ts +1 -1
  2. package/dist/packageVersion.js +1 -1
  3. package/dist/packageVersion.js.map +1 -1
  4. package/dist/runtime/extension/containerPresence.d.ts +1 -1
  5. package/dist/runtime/presenceDatastoreManager.d.ts +2 -2
  6. package/dist/runtime/presenceDatastoreManager.d.ts.map +1 -1
  7. package/dist/runtime/presenceDatastoreManager.js.map +1 -1
  8. package/dist/runtime/presenceManager.js.map +1 -1
  9. package/lib/packageVersion.d.ts +1 -1
  10. package/lib/packageVersion.js +1 -1
  11. package/lib/packageVersion.js.map +1 -1
  12. package/lib/runtime/extension/containerPresence.d.ts +1 -1
  13. package/lib/runtime/presenceDatastoreManager.d.ts +2 -2
  14. package/lib/runtime/presenceDatastoreManager.d.ts.map +1 -1
  15. package/lib/runtime/presenceDatastoreManager.js.map +1 -1
  16. package/lib/runtime/presenceManager.js.map +1 -1
  17. package/package.json +14 -14
  18. package/dist/runtime/test/presenceDatastoreManager.spec.js +0 -618
  19. package/dist/runtime/test/presenceDatastoreManager.spec.js.map +0 -1
  20. package/dist/runtime/test/presenceManager.spec.js +0 -651
  21. package/dist/runtime/test/presenceManager.spec.js.map +0 -1
  22. package/dist/states/test/batching.spec.js +0 -843
  23. package/dist/states/test/batching.spec.js.map +0 -1
  24. package/dist/states/test/broadcastControlsTests.js +0 -60
  25. package/dist/states/test/broadcastControlsTests.js.map +0 -1
  26. package/dist/states/test/eventing.spec.js +0 -576
  27. package/dist/states/test/eventing.spec.js.map +0 -1
  28. package/dist/states/test/latestMapValueManager.spec.js +0 -210
  29. package/dist/states/test/latestMapValueManager.spec.js.map +0 -1
  30. package/dist/states/test/latestValueManager.spec.js +0 -193
  31. package/dist/states/test/latestValueManager.spec.js.map +0 -1
  32. package/dist/states/test/mockEphemeralRuntime.js +0 -11
  33. package/dist/states/test/mockEphemeralRuntime.js.map +0 -1
  34. package/dist/states/test/notificationsManager.spec.js +0 -460
  35. package/dist/states/test/notificationsManager.spec.js.map +0 -1
  36. package/dist/states/test/presenceStates.spec.js +0 -73
  37. package/dist/states/test/presenceStates.spec.js.map +0 -1
  38. package/dist/states/test/schemaValidation/protocol.spec.js +0 -246
  39. package/dist/states/test/schemaValidation/protocol.spec.js.map +0 -1
  40. package/dist/states/test/schemaValidation/valueManagers.spec.js +0 -784
  41. package/dist/states/test/schemaValidation/valueManagers.spec.js.map +0 -1
  42. package/dist/states/test/testUtils.js +0 -21
  43. package/dist/states/test/testUtils.js.map +0 -1
  44. package/dist/test/mockEphemeralRuntime.js +0 -175
  45. package/dist/test/mockEphemeralRuntime.js.map +0 -1
  46. package/dist/test/testUtils.js +0 -262
  47. package/dist/test/testUtils.js.map +0 -1
  48. package/dist/test/utils/index.js +0 -27
  49. package/dist/test/utils/index.js.map +0 -1
  50. package/dist/utils/test/timerManager.spec.js +0 -93
  51. package/dist/utils/test/timerManager.spec.js.map +0 -1
  52. package/lib/runtime/test/presenceDatastoreManager.spec.js +0 -616
  53. package/lib/runtime/test/presenceDatastoreManager.spec.js.map +0 -1
  54. package/lib/runtime/test/presenceManager.spec.js +0 -649
  55. package/lib/runtime/test/presenceManager.spec.js.map +0 -1
  56. package/lib/states/test/batching.spec.js +0 -841
  57. package/lib/states/test/batching.spec.js.map +0 -1
  58. package/lib/states/test/broadcastControlsTests.js +0 -56
  59. package/lib/states/test/broadcastControlsTests.js.map +0 -1
  60. package/lib/states/test/eventing.spec.js +0 -574
  61. package/lib/states/test/eventing.spec.js.map +0 -1
  62. package/lib/states/test/latestMapValueManager.spec.js +0 -206
  63. package/lib/states/test/latestMapValueManager.spec.js.map +0 -1
  64. package/lib/states/test/latestValueManager.spec.js +0 -189
  65. package/lib/states/test/latestValueManager.spec.js.map +0 -1
  66. package/lib/states/test/mockEphemeralRuntime.js +0 -6
  67. package/lib/states/test/mockEphemeralRuntime.js.map +0 -1
  68. package/lib/states/test/notificationsManager.spec.js +0 -456
  69. package/lib/states/test/notificationsManager.spec.js.map +0 -1
  70. package/lib/states/test/presenceStates.spec.js +0 -69
  71. package/lib/states/test/presenceStates.spec.js.map +0 -1
  72. package/lib/states/test/schemaValidation/protocol.spec.js +0 -244
  73. package/lib/states/test/schemaValidation/protocol.spec.js.map +0 -1
  74. package/lib/states/test/schemaValidation/valueManagers.spec.js +0 -782
  75. package/lib/states/test/schemaValidation/valueManagers.spec.js.map +0 -1
  76. package/lib/states/test/testUtils.js +0 -6
  77. package/lib/states/test/testUtils.js.map +0 -1
  78. package/lib/test/mockEphemeralRuntime.js +0 -171
  79. package/lib/test/mockEphemeralRuntime.js.map +0 -1
  80. package/lib/test/testUtils.js +0 -251
  81. package/lib/test/testUtils.js.map +0 -1
  82. package/lib/test/utils/index.js +0 -8
  83. package/lib/test/utils/index.js.map +0 -1
  84. package/lib/utils/test/timerManager.spec.js +0 -91
  85. package/lib/utils/test/timerManager.spec.js.map +0 -1
@@ -1,616 +0,0 @@
1
- /*!
2
- * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
- * Licensed under the MIT License.
4
- */
5
- import { strict as assert } from "node:assert";
6
- import { validateAssertionError } from "@fluidframework/test-runtime-utils/internal";
7
- import { EventAndErrorTrackingLogger } from "@fluidframework/test-utils/internal";
8
- import { useFakeTimers, spy } from "sinon";
9
- import { assertFinalExpectations, attendeeId1, initialLocalClientConnectionId, localAttendeeId, createSpecificAttendeeId, MockEphemeralRuntime, prepareConnectedPresence, } from "@fluid-internal/presence-runtime/internal/test-utils";
10
- import { toOpaqueJson } from "@fluid-internal/presence-runtime/utils";
11
- import { broadcastJoinResponseDelaysMs } from "../presenceDatastoreManager.js";
12
- import { createPresenceManager } from "../presenceManager.js";
13
- const attendee0SystemWorkspaceDatastore = {
14
- "clientToSessionId": {
15
- ["client0"]: {
16
- "rev": 0,
17
- "timestamp": 0,
18
- "value": createSpecificAttendeeId("attendeeId-0"),
19
- },
20
- },
21
- };
22
- const attendee4SystemWorkspaceDatastore = {
23
- "clientToSessionId": {
24
- ["client4"]: {
25
- "rev": 0,
26
- "timestamp": 700,
27
- "value": createSpecificAttendeeId("attendeeId-4"),
28
- },
29
- },
30
- };
31
- const attendee5SystemWorkspaceDatastore = {
32
- "clientToSessionId": {
33
- ["client5"]: {
34
- "rev": 0,
35
- "timestamp": 800,
36
- "value": createSpecificAttendeeId("attendeeId-5"),
37
- },
38
- },
39
- };
40
- describe("Presence/Runtime", () => {
41
- describe("protocol handling", () => {
42
- let runtime;
43
- let logger;
44
- const initialTime = 1000;
45
- let clock;
46
- before(async () => {
47
- clock = useFakeTimers();
48
- });
49
- beforeEach(() => {
50
- logger = new EventAndErrorTrackingLogger();
51
- runtime = new MockEphemeralRuntime(logger);
52
- clock.setSystemTime(initialTime);
53
- });
54
- afterEach(function (done) {
55
- clock.reset();
56
- // If the test passed so far, check final expectations.
57
- if (this.currentTest?.state === "passed") {
58
- assertFinalExpectations(runtime, logger);
59
- }
60
- done();
61
- });
62
- after(() => {
63
- clock.restore();
64
- });
65
- it("does not signal when disconnected during initialization", () => {
66
- // Act & Verify
67
- createPresenceManager(runtime);
68
- });
69
- it("sends join when connected during initialization", () => {
70
- // Setup, Act (call to createPresenceManager), & Verify (post createPresenceManager call)
71
- prepareConnectedPresence(runtime, localAttendeeId, initialLocalClientConnectionId, clock, logger);
72
- });
73
- describe("handles ClientJoin", () => {
74
- let processSignal;
75
- beforeEach(() => {
76
- ({ processSignal } = prepareConnectedPresence(runtime, localAttendeeId, initialLocalClientConnectionId, clock, logger));
77
- // Pass a little time (to mimic reality)
78
- clock.tick(10);
79
- });
80
- function joinClients(updateProviders, delayToJoinClient5) {
81
- // Join client4
82
- processSignal([], {
83
- type: "Pres:ClientJoin",
84
- content: {
85
- sendTimestamp: clock.now - 50,
86
- avgLatency: 50,
87
- data: {
88
- "system:presence": attendee4SystemWorkspaceDatastore,
89
- },
90
- updateProviders,
91
- },
92
- clientId: "client4",
93
- }, false);
94
- if (delayToJoinClient5 !== undefined) {
95
- // Advance clock to delay joining client5
96
- clock.tick(delayToJoinClient5);
97
- // Join client5
98
- processSignal([], {
99
- type: "Pres:ClientJoin",
100
- content: {
101
- sendTimestamp: clock.now - 50,
102
- avgLatency: 50,
103
- data: {
104
- "system:presence": attendee5SystemWorkspaceDatastore,
105
- },
106
- updateProviders,
107
- },
108
- clientId: "client5",
109
- }, false);
110
- }
111
- }
112
- function processClient0ResponseForClient4() {
113
- // Setup
114
- // client 0 handles client 4 join
115
- processSignal([], {
116
- type: "Pres:DatastoreUpdate",
117
- content: {
118
- "avgLatency": 10,
119
- "data": {
120
- "system:presence": {
121
- "clientToSessionId": {
122
- ...attendee0SystemWorkspaceDatastore.clientToSessionId,
123
- ...attendee4SystemWorkspaceDatastore.clientToSessionId,
124
- },
125
- },
126
- },
127
- "isComplete": true,
128
- "joinResponseFor": ["client4"],
129
- "sendTimestamp": clock.now - 10,
130
- },
131
- clientId: "client0",
132
- }, false);
133
- }
134
- it(`when preferred responder ... with broadcast after ${broadcastJoinResponseDelaysMs.namedResponder}ms`, () => {
135
- // Setup
136
- const updateTime = clock.now + broadcastJoinResponseDelaysMs.namedResponder;
137
- // #region Part 1 (no response)
138
- // Act
139
- // join clients 4 and 5
140
- joinClients([initialLocalClientConnectionId], broadcastJoinResponseDelaysMs.namedResponder / 2);
141
- // Advance to one tick before expected response time
142
- clock.tick(updateTime - 1 - clock.now);
143
- // #endregion
144
- // #region Part 2 (response after delay)
145
- // Setup
146
- logger.registerExpectedEvent({
147
- eventName: "Presence:JoinResponse",
148
- details: JSON.stringify({
149
- type: "broadcastAll",
150
- attendeeId: localAttendeeId,
151
- connectionId: initialLocalClientConnectionId,
152
- primaryResponses: JSON.stringify(["client4", "client5"]),
153
- secondaryResponses: JSON.stringify([]),
154
- }),
155
- });
156
- runtime.signalsExpected.push([
157
- {
158
- type: "Pres:DatastoreUpdate",
159
- content: {
160
- "avgLatency": 10,
161
- "data": {
162
- "system:presence": {
163
- "clientToSessionId": {
164
- ...attendee4SystemWorkspaceDatastore.clientToSessionId,
165
- ...attendee5SystemWorkspaceDatastore.clientToSessionId,
166
- [initialLocalClientConnectionId]: {
167
- "rev": 0,
168
- "timestamp": initialTime,
169
- "value": localAttendeeId,
170
- },
171
- },
172
- },
173
- },
174
- "isComplete": true,
175
- "joinResponseFor": ["client4", "client5"],
176
- "sendTimestamp": clock.now + 1,
177
- },
178
- },
179
- ]);
180
- // Act
181
- clock.tick(1);
182
- // Verify
183
- assertFinalExpectations(runtime, logger);
184
- // #endregion
185
- });
186
- describe("when NOT preferred responder", () => {
187
- it("and no other responses ... with broadcast after delay", () => {
188
- // Setup
189
- const responseOrder = 2;
190
- // 3 * named length (client0 and client1) + quorum sequence order (third -> 2)
191
- const responderIndex = 3 * 2 + responseOrder;
192
- const updateTime = clock.now +
193
- broadcastJoinResponseDelaysMs.namedResponder +
194
- broadcastJoinResponseDelaysMs.backupResponderIncrement * responderIndex;
195
- // #region Part 1 (no response)
196
- // Act
197
- // join client 4
198
- joinClients(["client0", "client1"], undefined);
199
- clock.tick(updateTime - clock.now - 1);
200
- // #endregion
201
- // #region Part 2 (response after delay)
202
- // Setup
203
- logger.registerExpectedEvent({
204
- eventName: "Presence:JoinResponse",
205
- details: JSON.stringify({
206
- type: "broadcastAll",
207
- attendeeId: localAttendeeId,
208
- connectionId: initialLocalClientConnectionId,
209
- primaryResponses: JSON.stringify([]),
210
- secondaryResponses: JSON.stringify([["client4", responseOrder]]),
211
- }),
212
- });
213
- runtime.signalsExpected.push([
214
- {
215
- type: "Pres:DatastoreUpdate",
216
- content: {
217
- "avgLatency": 10,
218
- "data": {
219
- "system:presence": {
220
- "clientToSessionId": {
221
- ...attendee4SystemWorkspaceDatastore.clientToSessionId,
222
- [initialLocalClientConnectionId]: {
223
- "rev": 0,
224
- "timestamp": initialTime,
225
- "value": localAttendeeId,
226
- },
227
- },
228
- },
229
- },
230
- "isComplete": true,
231
- "joinResponseFor": ["client4"],
232
- "sendTimestamp": clock.now + 1,
233
- },
234
- },
235
- ]);
236
- // Act
237
- clock.tick(1);
238
- // Verify
239
- assertFinalExpectations(runtime, logger);
240
- // #endregion
241
- });
242
- it("and other has fully responded ... without broadcast", () => {
243
- // Setup
244
- // join client 4
245
- joinClients(["client0", "client1"], undefined);
246
- clock.tick(broadcastJoinResponseDelaysMs.namedResponder);
247
- // Act
248
- // client 0 handles client 4 join
249
- processClient0ResponseForClient4();
250
- clock.runAll();
251
- // Verify
252
- assertFinalExpectations(runtime, logger);
253
- });
254
- it("and other has partially responded ... with broadcast after delay", () => {
255
- // Setup
256
- const responseOrder = 2;
257
- // 3 * named length (client0 and client1) + quorum sequence order (third -> 2)
258
- const responderIndex = 3 * 2 + responseOrder;
259
- const client4ResponseDelay = broadcastJoinResponseDelaysMs.namedResponder +
260
- broadcastJoinResponseDelaysMs.backupResponderIncrement * responderIndex;
261
- const client4UpdateTime = clock.now + client4ResponseDelay;
262
- const delayToJoinClient5 = client4ResponseDelay / 2;
263
- const client5UpdateTime = client4UpdateTime + delayToJoinClient5;
264
- // join clients 4 and 5
265
- joinClients(["client0", "client1"], delayToJoinClient5);
266
- clock.tick(client4UpdateTime - clock.now - 1);
267
- // client 0 handles client 4 join
268
- processClient0ResponseForClient4();
269
- clock.tick(client5UpdateTime - clock.now - 1);
270
- logger.registerExpectedEvent({
271
- eventName: "Presence:JoinResponse",
272
- details: JSON.stringify({
273
- type: "broadcastAll",
274
- attendeeId: localAttendeeId,
275
- connectionId: initialLocalClientConnectionId,
276
- primaryResponses: JSON.stringify([]),
277
- secondaryResponses: JSON.stringify([["client5", responseOrder]]),
278
- }),
279
- });
280
- runtime.signalsExpected.push([
281
- {
282
- type: "Pres:DatastoreUpdate",
283
- content: {
284
- "avgLatency": 10,
285
- "data": {
286
- "system:presence": {
287
- "clientToSessionId": {
288
- ...attendee0SystemWorkspaceDatastore.clientToSessionId,
289
- ...attendee4SystemWorkspaceDatastore.clientToSessionId,
290
- ...attendee5SystemWorkspaceDatastore.clientToSessionId,
291
- [initialLocalClientConnectionId]: {
292
- "rev": 0,
293
- "timestamp": initialTime,
294
- "value": localAttendeeId,
295
- },
296
- },
297
- },
298
- },
299
- "isComplete": true,
300
- // Only responding for client5 (client4 has been handled)
301
- "joinResponseFor": ["client5"],
302
- "sendTimestamp": clock.now + 1,
303
- },
304
- },
305
- ]);
306
- // Act
307
- clock.tick(1);
308
- // Verify
309
- assertFinalExpectations(runtime, logger);
310
- // #endregion
311
- });
312
- });
313
- });
314
- describe("receiving DatastoreUpdate", () => {
315
- let presence;
316
- let processSignal;
317
- const systemWorkspaceUpdate = {
318
- "clientToSessionId": {
319
- "client1": {
320
- "rev": 0,
321
- "timestamp": 0,
322
- "value": attendeeId1,
323
- },
324
- },
325
- };
326
- const statesWorkspaceUpdate = {
327
- "latest": {
328
- [attendeeId1]: {
329
- "rev": 1,
330
- "timestamp": 0,
331
- "value": toOpaqueJson({}),
332
- },
333
- },
334
- };
335
- const notificationsWorkspaceUpdate = {
336
- "testEvents": {
337
- [attendeeId1]: {
338
- "rev": 0,
339
- "timestamp": 0,
340
- "value": toOpaqueJson({}),
341
- "ignoreUnmonitored": true,
342
- },
343
- },
344
- };
345
- beforeEach(() => {
346
- ({ presence, processSignal } = prepareConnectedPresence(runtime, localAttendeeId, initialLocalClientConnectionId, clock, logger));
347
- // Pass a little time (to mimic reality)
348
- clock.tick(10);
349
- });
350
- it("with unregistered States workspace emits 'workspaceActivated'", () => {
351
- // Setup
352
- const listener = spy();
353
- presence.events.on("workspaceActivated", listener);
354
- // Act
355
- processSignal([], {
356
- type: "Pres:DatastoreUpdate",
357
- content: {
358
- sendTimestamp: clock.now - 10,
359
- avgLatency: 20,
360
- data: {
361
- "system:presence": systemWorkspaceUpdate,
362
- "s:name:testStateWorkspace": statesWorkspaceUpdate,
363
- },
364
- },
365
- clientId: "client1",
366
- }, false);
367
- // Verify
368
- assert.strictEqual(listener.calledOnce, true);
369
- assert.strictEqual(listener.calledWith("name:testStateWorkspace", "States"), true);
370
- });
371
- it("with unregistered Notifications workspace 'workspaceActivated'", () => {
372
- // Setup
373
- const listener = spy();
374
- presence.events.on("workspaceActivated", listener);
375
- // Act
376
- processSignal([], {
377
- type: "Pres:DatastoreUpdate",
378
- content: {
379
- sendTimestamp: clock.now - 10,
380
- avgLatency: 20,
381
- data: {
382
- "system:presence": systemWorkspaceUpdate,
383
- "n:name:testNotificationWorkspace": notificationsWorkspaceUpdate,
384
- },
385
- },
386
- clientId: "client1",
387
- }, false);
388
- // Verify
389
- assert.strictEqual(listener.calledOnce, true);
390
- assert.strictEqual(listener.calledWith("name:testNotificationWorkspace", "Notifications"), true);
391
- });
392
- it("with unregistered workspace of unknown type emits 'workspaceActivated'", () => {
393
- // Setup
394
- const listener = spy();
395
- presence.events.on("workspaceActivated", listener);
396
- // Act
397
- processSignal([], {
398
- type: "Pres:DatastoreUpdate",
399
- content: {
400
- sendTimestamp: clock.now - 10,
401
- avgLatency: 20,
402
- data: {
403
- "system:presence": systemWorkspaceUpdate,
404
- ["u:name:testUnknownWorkspace"]: {
405
- "latest": {
406
- [attendeeId1]: {
407
- "rev": 1,
408
- "timestamp": 0,
409
- "value": toOpaqueJson({ x: 1, y: 1, z: 1 }),
410
- },
411
- },
412
- },
413
- },
414
- },
415
- clientId: "client1",
416
- }, false);
417
- // Verify
418
- assert.strictEqual(listener.calledOnce, true);
419
- assert.strictEqual(listener.calledWith("name:testUnknownWorkspace", "Unknown"), true);
420
- });
421
- it("with registered workspace does NOT emit 'workspaceActivated'", () => {
422
- // Setup
423
- const listener = spy();
424
- presence.events.on("workspaceActivated", listener);
425
- presence.states.getWorkspace("name:testStateWorkspace", {});
426
- presence.notifications.getWorkspace("name:testNotificationWorkspace", {});
427
- // Act
428
- processSignal([], {
429
- type: "Pres:DatastoreUpdate",
430
- content: {
431
- sendTimestamp: clock.now - 10,
432
- avgLatency: 20,
433
- data: {
434
- "system:presence": systemWorkspaceUpdate,
435
- "s:name:testStateWorkspace": statesWorkspaceUpdate,
436
- "n:name:testNotificationWorkspace": notificationsWorkspaceUpdate,
437
- },
438
- },
439
- clientId: "client1",
440
- }, false);
441
- // Verify
442
- assert.strictEqual(listener.called, false);
443
- });
444
- it("with workspace that has an unrecognized internal address does NOT emit 'workspaceActivated'", () => {
445
- // Setup
446
- const listener = spy();
447
- presence.events.on("workspaceActivated", listener);
448
- // Act
449
- processSignal([], {
450
- type: "Pres:DatastoreUpdate",
451
- content: {
452
- sendTimestamp: clock.now - 10,
453
- avgLatency: 20,
454
- data: {
455
- "system:presence": systemWorkspaceUpdate,
456
- // Unrecognized internal address
457
- ["sn:name:testStateWorkspace"]: statesWorkspaceUpdate,
458
- },
459
- },
460
- clientId: "client1",
461
- }, false);
462
- // Verify
463
- assert.strictEqual(listener.called, false);
464
- });
465
- it("with workspace that has an invalid public address does NOT emit 'workspaceActivated'", () => {
466
- // Setup
467
- const listener = spy();
468
- presence.events.on("workspaceActivated", listener);
469
- // Act
470
- processSignal([], {
471
- type: "Pres:DatastoreUpdate",
472
- content: {
473
- sendTimestamp: clock.now - 10,
474
- avgLatency: 20,
475
- data: {
476
- "system:presence": systemWorkspaceUpdate,
477
- // Invalid public address (must be `${string}:${string}`)
478
- ["s:testStateWorkspace"]: statesWorkspaceUpdate,
479
- },
480
- },
481
- clientId: "client1",
482
- }, false);
483
- // Verify
484
- assert.strictEqual(listener.called, false);
485
- });
486
- it("with workspace that has already been seen does NOT emit 'workspaceActivated'", () => {
487
- // Setup
488
- const listener = spy();
489
- presence.events.on("workspaceActivated", listener);
490
- // Act
491
- processSignal([], {
492
- type: "Pres:DatastoreUpdate",
493
- content: {
494
- sendTimestamp: clock.now - 20,
495
- avgLatency: 20,
496
- data: {
497
- "system:presence": systemWorkspaceUpdate,
498
- "s:name:testStateWorkspace": statesWorkspaceUpdate,
499
- },
500
- },
501
- clientId: "client1",
502
- }, false);
503
- processSignal([], {
504
- type: "Pres:DatastoreUpdate",
505
- content: {
506
- sendTimestamp: clock.now - 10,
507
- avgLatency: 20,
508
- data: {
509
- "system:presence": systemWorkspaceUpdate,
510
- "s:name:testStateWorkspace": statesWorkspaceUpdate,
511
- },
512
- },
513
- clientId: "client1",
514
- }, false);
515
- // Verify
516
- assert.strictEqual(listener.callCount, 1);
517
- });
518
- it("with acknowledgementId sends targeted acknowledgment message back to requestor", () => {
519
- // We expect to send a targeted acknowledgment back to the requestor
520
- runtime.signalsExpected.push([
521
- {
522
- type: "Pres:Ack",
523
- content: { id: "ackID" },
524
- targetClientId: "client4",
525
- },
526
- ]);
527
- // Act - send generic datastore update with acknowledgement id specified
528
- processSignal([], {
529
- type: "Pres:DatastoreUpdate",
530
- content: {
531
- sendTimestamp: clock.now - 10,
532
- avgLatency: 20,
533
- data: {
534
- "system:presence": systemWorkspaceUpdate,
535
- "s:name:testStateWorkspace": statesWorkspaceUpdate,
536
- },
537
- acknowledgementId: "ackID",
538
- },
539
- clientId: "client4",
540
- }, false);
541
- // Verify
542
- assertFinalExpectations(runtime, logger);
543
- });
544
- });
545
- describe("receiving unrecognized message", () => {
546
- let presence;
547
- let processSignal;
548
- const systemWorkspaceUpdate = {
549
- "clientToSessionId": {
550
- "client1": {
551
- "rev": 0,
552
- "timestamp": 0,
553
- "value": attendeeId1,
554
- },
555
- },
556
- };
557
- const statesWorkspaceUpdate = {
558
- "latest": {
559
- [attendeeId1]: {
560
- "rev": 1,
561
- "timestamp": 0,
562
- "value": toOpaqueJson({}),
563
- },
564
- },
565
- };
566
- beforeEach(() => {
567
- ({ presence, processSignal } = prepareConnectedPresence(runtime, localAttendeeId, initialLocalClientConnectionId, clock, logger));
568
- // Pass a little time (to mimic reality)
569
- clock.tick(10);
570
- });
571
- /**
572
- * Use to pretend any general inbound message is an unverified Presence message
573
- */
574
- function markUnverifiedIncomingMessage(
575
- // make sure message "was" at least serializable
576
- message) {
577
- return message;
578
- }
579
- function processUnrecognizedMessage({ optional }) {
580
- // Mocked to look very much like a Presence message, but with an unrecognized type.
581
- const unrecognizedMessage = {
582
- type: "Pres: Unrecognized Message",
583
- content: {
584
- sendTimestamp: clock.now - 10,
585
- avgLatency: 20,
586
- data: {
587
- "system:presence": systemWorkspaceUpdate,
588
- "s:name:testStateWorkspace": statesWorkspaceUpdate,
589
- },
590
- },
591
- clientId: "client1",
592
- };
593
- processSignal(optional ? ["?"] : [], markUnverifiedIncomingMessage(unrecognizedMessage), false);
594
- }
595
- it("that is NOT optional, throws", () => {
596
- // Setup
597
- const listener = spy();
598
- presence.events.on("workspaceActivated", listener);
599
- // Act & Verify
600
- assert.throws(() => processUnrecognizedMessage({ optional: false }), validateAssertionError("0xcbc"));
601
- // Verify
602
- assert.strictEqual(listener.called, false);
603
- });
604
- it("that is optional, ignores message and does NOT throw", () => {
605
- // Setup
606
- const listener = spy();
607
- presence.events.on("workspaceActivated", listener);
608
- // Act & Verify
609
- processUnrecognizedMessage({ optional: true });
610
- // Verify
611
- assert.strictEqual(listener.called, false);
612
- });
613
- });
614
- });
615
- });
616
- //# sourceMappingURL=presenceDatastoreManager.spec.js.map