@fluid-internal/presence-runtime 2.102.0 → 2.110.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 +15 -15
  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,456 +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, fail } from "node:assert";
6
- import { EventAndErrorTrackingLogger } from "@fluidframework/test-utils/internal";
7
- import { useFakeTimers } from "sinon";
8
- import { Notifications, StateFactory } from "@fluid-internal/presence-runtime/states";
9
- import { toOpaqueJson } from "@fluid-internal/presence-runtime/utils";
10
- import { MockEphemeralRuntime } from "./mockEphemeralRuntime.js";
11
- import { assertFinalExpectations, assertIdenticalTypes, initialLocalClientConnectionId, createInstanceOf, createSpecificAttendeeId, prepareConnectedPresence, localAttendeeId, } from "./testUtils.js";
12
- const attendeeId3 = createSpecificAttendeeId("attendeeId-3");
13
- const connectionId3 = "client3";
14
- describe("Presence/States", () => {
15
- describe("Notifications Workspace", () => {
16
- /**
17
- * See {@link checkCompiles} below
18
- */
19
- it("API use compiles", () => { });
20
- });
21
- describe("NotificationsManager", () => {
22
- // Note: this test setup mimics the setup in src/test/presenceManager.spec.ts
23
- let runtime;
24
- let logger;
25
- const initialTime = 1000;
26
- let clock;
27
- let presence;
28
- let processSignal;
29
- before(async () => {
30
- clock = useFakeTimers();
31
- });
32
- beforeEach(() => {
33
- logger = new EventAndErrorTrackingLogger();
34
- runtime = new MockEphemeralRuntime(logger);
35
- // We are configuring the runtime to be in a connected state, so ensure it looks connected
36
- runtime.joined = true;
37
- clock.setSystemTime(initialTime);
38
- // Set up the presence connection
39
- ({ presence, processSignal } = prepareConnectedPresence(runtime, localAttendeeId, initialLocalClientConnectionId, clock, logger));
40
- });
41
- afterEach(function (done) {
42
- clock.reset();
43
- // If the test passed so far, check final expectations.
44
- if (this.currentTest?.state === "passed") {
45
- assertFinalExpectations(runtime, logger);
46
- }
47
- done();
48
- });
49
- after(() => {
50
- clock.restore();
51
- });
52
- it("can be created with explicit schema via `Notifications` in `getWorkspace` schema", () => {
53
- // Act
54
- const notificationsWorkspace = presence.notifications.getWorkspace("name:testNotificationWorkspace", {
55
- "testEvents": Notifications(
56
- // A default handler is not required
57
- {}),
58
- });
59
- // Verify
60
- assert.notEqual(notificationsWorkspace.notifications.testEvents, undefined);
61
- assertIdenticalTypes(notificationsWorkspace.notifications.testEvents, createInstanceOf());
62
- });
63
- it("can be created with inferred schema via `Notifications` in `getWorkspace` schema", () => {
64
- // Act
65
- const notificationsWorkspace = presence.notifications.getWorkspace("name:testNotificationWorkspace", {
66
- "testEvents": Notifications({
67
- newId: (_attendee, _id) => { },
68
- }),
69
- });
70
- // Verify
71
- assert.notEqual(notificationsWorkspace.notifications.testEvents, undefined);
72
- assertIdenticalTypes(notificationsWorkspace.notifications.testEvents, createInstanceOf());
73
- });
74
- it("can be created via `Notifications` added to workspace", async () => {
75
- const notificationsWorkspace = presence.notifications.getWorkspace("name:testNotificationWorkspace", {});
76
- // Act
77
- notificationsWorkspace.add("testEvents", Notifications(
78
- // A default handler is not required
79
- {}));
80
- // Verify
81
- assert.notEqual(notificationsWorkspace.notifications.testEvents, undefined);
82
- assertIdenticalTypes(notificationsWorkspace.notifications.testEvents, createInstanceOf());
83
- });
84
- it("typing won't be updated attempting duplicate `add` to workspace with different schema", () => {
85
- const notificationsWorkspace = presence.notifications.getWorkspace("name:testNotifications", {
86
- testEvents: Notifications({
87
- hotSpot: (_sender, _) => { },
88
- }),
89
- });
90
- // For type checking that "hotSpot" is a valid event name
91
- notificationsWorkspace.notifications.testEvents.notifications.on("hotSpot", (_sender, _position) => { });
92
- // Workaround ts(2775): Assertions require every name in the call target to be declared with an explicit type annotation.
93
- const workspace = notificationsWorkspace;
94
- // Act
95
- assert.throws(() => {
96
- workspace.add(
97
- // Same name as existing NotificationsManager
98
- "testEvents",
99
- // Different schema than existing NotificationsManager
100
- Notifications({}));
101
- });
102
- // Verify
103
- // Typing is unchanged - "moveCaret" is not a valid event name
104
- workspace.notifications.testEvents.notifications.on(
105
- // @ts-expect-error - "moveCaret" is not a valid event name
106
- "moveCaret", () => { });
107
- // For type checking that "hotSpot" is still a valid event name
108
- workspace.notifications.testEvents.notifications.on("hotSpot",
109
- // @ts-expect-error - "position" is the wrong type
110
- (_sender, _position) => { });
111
- });
112
- it("can be created with explicit schema and partial subscribers via `Notifications`", () => {
113
- // Act
114
- const notificationsWorkspace = presence.notifications.getWorkspace("name:testNotificationWorkspace", {
115
- "testEvents": Notifications({
116
- newId: (_attendee, _id) => { },
117
- }),
118
- });
119
- // Verify
120
- assert.notEqual(notificationsWorkspace.notifications.testEvents, undefined);
121
- assertIdenticalTypes(notificationsWorkspace.notifications.testEvents, createInstanceOf());
122
- });
123
- it("strips bad events when created with improperly typed subscribers", () => {
124
- // Act
125
- const notificationsWorkspace = presence.notifications.getWorkspace("name:testNotificationWorkspace", {
126
- "testEvents": Notifications({
127
- missingAttendeeParam: (_id) => { },
128
- nonSerializableArg: (_attendee, _fn) => { },
129
- okay: (_attendee, _id) => { },
130
- }),
131
- });
132
- // Verify
133
- assert.notEqual(notificationsWorkspace.notifications.testEvents, undefined);
134
- assertIdenticalTypes(notificationsWorkspace.notifications.testEvents, createInstanceOf());
135
- });
136
- it("emit.broadcast sends broadcast signal", async () => {
137
- // Setup
138
- const notificationsWorkspace = presence.notifications.getWorkspace("name:testNotificationWorkspace", {
139
- "testEvents": Notifications({
140
- newId: (_attendee, _id) => { },
141
- }),
142
- });
143
- const { testEvents } = notificationsWorkspace.notifications;
144
- clock.tick(10);
145
- runtime.signalsExpected.push([
146
- {
147
- type: "Pres:DatastoreUpdate",
148
- content: {
149
- "sendTimestamp": clock.now,
150
- "avgLatency": 10,
151
- "data": {
152
- "system:presence": {
153
- "clientToSessionId": {
154
- [initialLocalClientConnectionId]: {
155
- "rev": 0,
156
- "timestamp": initialTime,
157
- "value": localAttendeeId,
158
- },
159
- },
160
- },
161
- "n:name:testNotificationWorkspace": {
162
- "testEvents": {
163
- [localAttendeeId]: {
164
- "rev": 0,
165
- "timestamp": 0,
166
- "value": toOpaqueJson({ "name": "newId", "args": [42] }),
167
- "ignoreUnmonitored": true,
168
- },
169
- },
170
- },
171
- },
172
- },
173
- },
174
- ]);
175
- // Act & Verify
176
- testEvents.emit.broadcast("newId", 42);
177
- assertFinalExpectations(runtime, logger);
178
- });
179
- // TODO: Implement `unicast` method in NotificationsManager and in supporting code.
180
- it.skip("emit.unicast sends directed signal", async () => {
181
- // Setup
182
- const notificationsWorkspace = presence.notifications.getWorkspace("name:testNotificationWorkspace", {
183
- "testEvents": Notifications({
184
- newId: (_attendee, _id) => { },
185
- }),
186
- });
187
- const { testEvents } = notificationsWorkspace.notifications;
188
- clock.tick(10);
189
- runtime.signalsExpected.push([
190
- {
191
- type: "Pres:DatastoreUpdate",
192
- content: {
193
- "sendTimestamp": clock.now,
194
- "avgLatency": 10,
195
- "data": {
196
- "system:presence": {
197
- "clientToSessionId": {
198
- [initialLocalClientConnectionId]: {
199
- "rev": 0,
200
- "timestamp": initialTime,
201
- "value": localAttendeeId,
202
- },
203
- },
204
- },
205
- "n:name:testNotificationWorkspace": {
206
- "testEvents": {
207
- [localAttendeeId]: {
208
- "rev": 0,
209
- "timestamp": 0,
210
- "value": toOpaqueJson({ "name": "newId", "args": [42] }),
211
- "ignoreUnmonitored": true,
212
- },
213
- },
214
- },
215
- },
216
- },
217
- // Targeting self for simplicity
218
- targetClientId: initialLocalClientConnectionId,
219
- },
220
- ]);
221
- // Act & Verify
222
- testEvents.emit.unicast("newId", presence.attendees.getMyself(), 42);
223
- assertFinalExpectations(runtime, logger);
224
- });
225
- it("raises named event when notification is received", async () => {
226
- const eventHandlerCalls = {
227
- original: [],
228
- secondary: [],
229
- tertiary: [],
230
- };
231
- function originalEventHandler(attendee, id) {
232
- assert.equal(attendee.attendeeId, attendeeId3);
233
- assert.equal(id, 42);
234
- eventHandlerCalls.original.push({ attendee, id });
235
- }
236
- const notificationsWorkspace = presence.notifications.getWorkspace("name:testNotificationWorkspace", {
237
- "testEvents": Notifications({
238
- newId: originalEventHandler,
239
- }),
240
- });
241
- const { testEvents } = notificationsWorkspace.notifications;
242
- testEvents.events.on("unattendedNotification", (name) => {
243
- fail(`Unexpected unattendedNotification: ${name}`);
244
- });
245
- const disconnectFunctions = [
246
- testEvents.notifications.on("newId", (attendee, id) => {
247
- eventHandlerCalls.secondary.push({ attendee, id });
248
- }),
249
- testEvents.notifications.on("newId", (attendee, id) => {
250
- eventHandlerCalls.tertiary.push({ attendee, id });
251
- }),
252
- ];
253
- // Processing this signal should trigger the testEvents.newId event listeners
254
- processSignal([], {
255
- type: "Pres:DatastoreUpdate",
256
- content: {
257
- "sendTimestamp": 1020,
258
- "avgLatency": 10,
259
- "data": {
260
- "system:presence": {
261
- "clientToSessionId": {
262
- [connectionId3]: { "rev": 0, "timestamp": 1000, "value": attendeeId3 },
263
- },
264
- },
265
- "n:name:testNotificationWorkspace": {
266
- "testEvents": {
267
- [attendeeId3]: {
268
- "rev": 0,
269
- "timestamp": 0,
270
- "value": toOpaqueJson({ "name": "newId", "args": [42] }),
271
- "ignoreUnmonitored": true,
272
- },
273
- },
274
- },
275
- },
276
- },
277
- clientId: "client3",
278
- }, false);
279
- assert(eventHandlerCalls.original.length === 1, `original event handler was called ${eventHandlerCalls.original.length} times; expected 1`);
280
- assert(eventHandlerCalls.secondary.length === 1, `secondary event handler was called ${eventHandlerCalls.secondary.length} times; expected 1`);
281
- assert(eventHandlerCalls.tertiary.length === 1, `secondary event handler was called ${eventHandlerCalls.tertiary.length} times; expected 1`);
282
- // Cleanup
283
- for (const disconnect of disconnectFunctions) {
284
- disconnect();
285
- }
286
- });
287
- it("raises `unattendedEvent` event when unrecognized notification is received", async () => {
288
- let unattendedEventCalled = false;
289
- const notificationsWorkspace = presence.notifications.getWorkspace("name:testNotificationWorkspace", {
290
- "testEvents": Notifications({
291
- newId: (attendee, id) => {
292
- fail(`Unexpected newId event`);
293
- },
294
- }),
295
- });
296
- const { testEvents } = notificationsWorkspace.notifications;
297
- testEvents.events.on("unattendedNotification", (name, sender, ...content) => {
298
- assert.equal(name, "oldId");
299
- assert.equal(sender.attendeeId, attendeeId3);
300
- assert.deepEqual(content, [41]);
301
- assert(!unattendedEventCalled);
302
- unattendedEventCalled = true;
303
- });
304
- // Processing this signal should trigger the testEvents.newId event listeners
305
- processSignal([], {
306
- type: "Pres:DatastoreUpdate",
307
- content: {
308
- "sendTimestamp": 1020,
309
- "avgLatency": 10,
310
- "data": {
311
- "system:presence": {
312
- "clientToSessionId": {
313
- [connectionId3]: { "rev": 0, "timestamp": 1000, "value": attendeeId3 },
314
- },
315
- },
316
- "n:name:testNotificationWorkspace": {
317
- "testEvents": {
318
- [attendeeId3]: {
319
- "rev": 0,
320
- "timestamp": 0,
321
- "value": toOpaqueJson({ "name": "oldId", "args": [41] }),
322
- "ignoreUnmonitored": true,
323
- },
324
- },
325
- },
326
- },
327
- },
328
- clientId: "client3",
329
- }, false);
330
- assert(unattendedEventCalled, "unattendedEvent not called");
331
- });
332
- it("raises `unattendedEvent` event when recognized notification is received without listeners", async () => {
333
- let unattendedEventCalled = false;
334
- function newIdEventHandler(attendee, id) {
335
- fail(`Unexpected newId event`);
336
- }
337
- const notificationsWorkspace = presence.notifications.getWorkspace("name:testNotificationWorkspace", {
338
- "testEvents": Notifications({
339
- newId: newIdEventHandler,
340
- }),
341
- });
342
- const { testEvents } = notificationsWorkspace.notifications;
343
- testEvents.events.on("unattendedNotification", (name, sender, ...content) => {
344
- assert.equal(name, "newId");
345
- assert.equal(sender.attendeeId, attendeeId3);
346
- assert.deepEqual(content, [43]);
347
- assert(!unattendedEventCalled);
348
- unattendedEventCalled = true;
349
- });
350
- testEvents.notifications.off("newId", newIdEventHandler);
351
- // Processing this signal should trigger the testEvents.newId event listeners
352
- processSignal([], {
353
- type: "Pres:DatastoreUpdate",
354
- content: {
355
- "sendTimestamp": 1020,
356
- "avgLatency": 10,
357
- "data": {
358
- "system:presence": {
359
- "clientToSessionId": {
360
- [connectionId3]: { "rev": 0, "timestamp": 1000, "value": attendeeId3 },
361
- },
362
- },
363
- "n:name:testNotificationWorkspace": {
364
- "testEvents": {
365
- [attendeeId3]: {
366
- "rev": 0,
367
- "timestamp": 0,
368
- "value": toOpaqueJson({ "name": "newId", "args": [43] }),
369
- "ignoreUnmonitored": true,
370
- },
371
- },
372
- },
373
- },
374
- },
375
- clientId: "client3",
376
- }, false);
377
- assert(unattendedEventCalled, "unattendedEvent not called");
378
- });
379
- it("removed listeners are not called when related notification is received", async () => {
380
- let originalEventHandlerCalled = false;
381
- function originalEventHandler(attendee, id) {
382
- assert.equal(attendee.attendeeId, attendeeId3);
383
- assert.equal(id, 44);
384
- assert.equal(originalEventHandlerCalled, false);
385
- originalEventHandlerCalled = true;
386
- }
387
- const notificationsWorkspace = presence.notifications.getWorkspace("name:testNotificationWorkspace", {
388
- "testEvents": Notifications({
389
- newId: originalEventHandler,
390
- }),
391
- });
392
- const { testEvents } = notificationsWorkspace.notifications;
393
- testEvents.events.on("unattendedNotification", (name) => {
394
- fail(`Unexpected unattendedNotification: ${name}`);
395
- });
396
- const disconnect = testEvents.notifications.on("newId", (_attendee, _id) => {
397
- fail(`Unexpected event raised on disconnected listener`);
398
- });
399
- // Remove the listener
400
- disconnect();
401
- // Act
402
- processSignal([], {
403
- type: "Pres:DatastoreUpdate",
404
- content: {
405
- "sendTimestamp": 1020,
406
- "avgLatency": 10,
407
- "data": {
408
- "system:presence": {
409
- "clientToSessionId": {
410
- [connectionId3]: { "rev": 0, "timestamp": 1000, "value": attendeeId3 },
411
- },
412
- },
413
- "n:name:testNotificationWorkspace": {
414
- "testEvents": {
415
- [attendeeId3]: {
416
- "rev": 0,
417
- "timestamp": 0,
418
- "value": toOpaqueJson({ "name": "newId", "args": [44] }),
419
- "ignoreUnmonitored": true,
420
- },
421
- },
422
- },
423
- },
424
- },
425
- clientId: "client3",
426
- }, false);
427
- // Verify
428
- assert(originalEventHandlerCalled, "originalEventHandler not called");
429
- });
430
- it(".presence provides Presence it was created under", () => {
431
- const notificationsWorkspace = presence.notifications.getWorkspace("name:testNotificationWorkspace", {
432
- "testEvents": Notifications(
433
- // A default handler is not required
434
- {}),
435
- });
436
- assert.strictEqual(notificationsWorkspace.notifications.testEvents.presence, presence);
437
- assert.strictEqual(notificationsWorkspace.presence, presence);
438
- });
439
- });
440
- });
441
- // ---- test (example) code ----
442
- /**
443
- * Check that the code compiles.
444
- */
445
- export function checkCompiles() {
446
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
447
- const presence = {};
448
- presence.notifications.getWorkspace("name:testNotifications", {
449
- testEvents: Notifications({
450
- hotSpot: (_sender, _) => { },
451
- }),
452
- // @ts-expect-error - Notifications Workspace only permits NotificationsManagers
453
- camera: StateFactory.latest({ local: { x: 0, y: 0, z: 0 } }),
454
- });
455
- }
456
- //# sourceMappingURL=notificationsManager.spec.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"notificationsManager.spec.js","sourceRoot":"","sources":["../../../src/states/test/notificationsManager.spec.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { strict as assert, fail } from \"node:assert\";\n\nimport type {\n\tAttendee,\n\tClientConnectionId,\n\tNotificationsManager,\n\tNotificationsWorkspace,\n\tPresenceWithNotifications,\n} from \"@fluid-internal/presence-definitions\";\nimport { EventAndErrorTrackingLogger } from \"@fluidframework/test-utils/internal\";\nimport type { SinonFakeTimers } from \"sinon\";\nimport { useFakeTimers } from \"sinon\";\n\nimport { Notifications, StateFactory } from \"@fluid-internal/presence-runtime/states\";\nimport { toOpaqueJson } from \"@fluid-internal/presence-runtime/utils\";\n\nimport { MockEphemeralRuntime } from \"./mockEphemeralRuntime.js\";\nimport type { ProcessSignalFunction } from \"./testUtils.js\";\nimport {\n\tassertFinalExpectations,\n\tassertIdenticalTypes,\n\tinitialLocalClientConnectionId,\n\tcreateInstanceOf,\n\tcreateSpecificAttendeeId,\n\tprepareConnectedPresence,\n\tlocalAttendeeId,\n} from \"./testUtils.js\";\n\nconst attendeeId3 = createSpecificAttendeeId(\"attendeeId-3\");\nconst connectionId3 = \"client3\" as const satisfies ClientConnectionId;\n\ndescribe(\"Presence/States\", () => {\n\tdescribe(\"Notifications Workspace\", () => {\n\t\t/**\n\t\t * See {@link checkCompiles} below\n\t\t */\n\t\tit(\"API use compiles\", () => {});\n\t});\n\n\tdescribe(\"NotificationsManager\", () => {\n\t\t// Note: this test setup mimics the setup in src/test/presenceManager.spec.ts\n\t\tlet runtime: MockEphemeralRuntime;\n\t\tlet logger: EventAndErrorTrackingLogger;\n\t\tconst initialTime = 1000;\n\t\tlet clock: SinonFakeTimers;\n\t\tlet presence: PresenceWithNotifications;\n\t\tlet processSignal: ProcessSignalFunction;\n\n\t\tbefore(async () => {\n\t\t\tclock = useFakeTimers();\n\t\t});\n\n\t\tbeforeEach(() => {\n\t\t\tlogger = new EventAndErrorTrackingLogger();\n\t\t\truntime = new MockEphemeralRuntime(logger);\n\n\t\t\t// We are configuring the runtime to be in a connected state, so ensure it looks connected\n\t\t\truntime.joined = true;\n\n\t\t\tclock.setSystemTime(initialTime);\n\n\t\t\t// Set up the presence connection\n\t\t\t({ presence, processSignal } = prepareConnectedPresence(\n\t\t\t\truntime,\n\t\t\t\tlocalAttendeeId,\n\t\t\t\tinitialLocalClientConnectionId,\n\t\t\t\tclock,\n\t\t\t\tlogger,\n\t\t\t));\n\t\t});\n\n\t\tafterEach(function (done: Mocha.Done) {\n\t\t\tclock.reset();\n\n\t\t\t// If the test passed so far, check final expectations.\n\t\t\tif (this.currentTest?.state === \"passed\") {\n\t\t\t\tassertFinalExpectations(runtime, logger);\n\t\t\t}\n\t\t\tdone();\n\t\t});\n\n\t\tafter(() => {\n\t\t\tclock.restore();\n\t\t});\n\n\t\tit(\"can be created with explicit schema via `Notifications` in `getWorkspace` schema\", () => {\n\t\t\t// Act\n\t\t\tconst notificationsWorkspace = presence.notifications.getWorkspace(\n\t\t\t\t\"name:testNotificationWorkspace\",\n\t\t\t\t{\n\t\t\t\t\t\"testEvents\": Notifications<{\n\t\t\t\t\t\tnewId: (id: number) => void;\n\t\t\t\t\t}>(\n\t\t\t\t\t\t// A default handler is not required\n\t\t\t\t\t\t{},\n\t\t\t\t\t),\n\t\t\t\t},\n\t\t\t);\n\n\t\t\t// Verify\n\t\t\tassert.notEqual(notificationsWorkspace.notifications.testEvents, undefined);\n\t\t\tassertIdenticalTypes(\n\t\t\t\tnotificationsWorkspace.notifications.testEvents,\n\t\t\t\tcreateInstanceOf<NotificationsManager<{ newId: (id: number) => void }>>(),\n\t\t\t);\n\t\t});\n\n\t\tit(\"can be created with inferred schema via `Notifications` in `getWorkspace` schema\", () => {\n\t\t\t// Act\n\t\t\tconst notificationsWorkspace = presence.notifications.getWorkspace(\n\t\t\t\t\"name:testNotificationWorkspace\",\n\t\t\t\t{\n\t\t\t\t\t\"testEvents\": Notifications({\n\t\t\t\t\t\tnewId: (_attendee: Attendee, _id: number) => {},\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t);\n\n\t\t\t// Verify\n\t\t\tassert.notEqual(notificationsWorkspace.notifications.testEvents, undefined);\n\t\t\tassertIdenticalTypes(\n\t\t\t\tnotificationsWorkspace.notifications.testEvents,\n\t\t\t\tcreateInstanceOf<NotificationsManager<{ newId: (id: number) => void }>>(),\n\t\t\t);\n\t\t});\n\n\t\tit(\"can be created via `Notifications` added to workspace\", async () => {\n\t\t\t// Setup\n\t\t\t// Get an empty notifications workspace\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-empty-object-type\n\t\t\ttype EmptyNotificationsWorkspace = NotificationsWorkspace<{}>;\n\t\t\tconst notificationsWorkspace: EmptyNotificationsWorkspace =\n\t\t\t\tpresence.notifications.getWorkspace(\"name:testNotificationWorkspace\", {});\n\n\t\t\t// Act\n\t\t\tnotificationsWorkspace.add(\n\t\t\t\t\"testEvents\",\n\t\t\t\tNotifications<{\n\t\t\t\t\tnewId: (id: number) => void;\n\t\t\t\t}>(\n\t\t\t\t\t// A default handler is not required\n\t\t\t\t\t{},\n\t\t\t\t),\n\t\t\t);\n\n\t\t\t// Verify\n\t\t\tassert.notEqual(notificationsWorkspace.notifications.testEvents, undefined);\n\t\t\tassertIdenticalTypes(\n\t\t\t\tnotificationsWorkspace.notifications.testEvents,\n\t\t\t\tcreateInstanceOf<NotificationsManager<{ newId: (id: number) => void }>>(),\n\t\t\t);\n\t\t});\n\n\t\tit(\"typing won't be updated attempting duplicate `add` to workspace with different schema\", () => {\n\t\t\tconst notificationsWorkspace = presence.notifications.getWorkspace(\n\t\t\t\t\"name:testNotifications\",\n\t\t\t\t{\n\t\t\t\t\ttestEvents: Notifications({\n\t\t\t\t\t\thotSpot: (_sender: Attendee, _: { x: number; y: number }): void => {},\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t);\n\t\t\t// For type checking that \"hotSpot\" is a valid event name\n\t\t\tnotificationsWorkspace.notifications.testEvents.notifications.on(\n\t\t\t\t\"hotSpot\",\n\t\t\t\t(_sender: Attendee, _position: { x: number; y: number }) => {},\n\t\t\t);\n\n\t\t\t// Workaround ts(2775): Assertions require every name in the call target to be declared with an explicit type annotation.\n\t\t\tconst workspace: typeof notificationsWorkspace = notificationsWorkspace;\n\n\t\t\t// Act\n\t\t\tassert.throws(() => {\n\t\t\t\tworkspace.add(\n\t\t\t\t\t// Same name as existing NotificationsManager\n\t\t\t\t\t\"testEvents\",\n\t\t\t\t\t// Different schema than existing NotificationsManager\n\t\t\t\t\tNotifications<{\n\t\t\t\t\t\tmoveCaret: (moveDetails: { id: string; pos: number }) => void;\n\t\t\t\t\t}>({}),\n\t\t\t\t);\n\t\t\t});\n\n\t\t\t// Verify\n\t\t\t// Typing is unchanged - \"moveCaret\" is not a valid event name\n\t\t\tworkspace.notifications.testEvents.notifications.on(\n\t\t\t\t// @ts-expect-error - \"moveCaret\" is not a valid event name\n\t\t\t\t\"moveCaret\",\n\t\t\t\t() => {},\n\t\t\t);\n\n\t\t\t// For type checking that \"hotSpot\" is still a valid event name\n\t\t\tworkspace.notifications.testEvents.notifications.on(\n\t\t\t\t\"hotSpot\",\n\t\t\t\t// @ts-expect-error - \"position\" is the wrong type\n\t\t\t\t(_sender: Attendee, _position: number) => {},\n\t\t\t);\n\t\t});\n\n\t\tit(\"can be created with explicit schema and partial subscribers via `Notifications`\", () => {\n\t\t\t// Act\n\t\t\tconst notificationsWorkspace = presence.notifications.getWorkspace(\n\t\t\t\t\"name:testNotificationWorkspace\",\n\t\t\t\t{\n\t\t\t\t\t\"testEvents\": Notifications<{\n\t\t\t\t\t\tnewId: (id: number) => void;\n\t\t\t\t\t\thotSpot: (pos: { x: number; y: number }) => void;\n\t\t\t\t\t}>({\n\t\t\t\t\t\tnewId: (_attendee: Attendee, _id: number) => {},\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t);\n\n\t\t\t// Verify\n\t\t\tassert.notEqual(notificationsWorkspace.notifications.testEvents, undefined);\n\t\t\tassertIdenticalTypes(\n\t\t\t\tnotificationsWorkspace.notifications.testEvents,\n\t\t\t\tcreateInstanceOf<\n\t\t\t\t\tNotificationsManager<{\n\t\t\t\t\t\tnewId: (id: number) => void;\n\t\t\t\t\t\thotSpot: (pos: { x: number; y: number }) => void;\n\t\t\t\t\t}>\n\t\t\t\t>(),\n\t\t\t);\n\t\t});\n\n\t\tit(\"strips bad events when created with improperly typed subscribers\", () => {\n\t\t\t// Act\n\t\t\tconst notificationsWorkspace = presence.notifications.getWorkspace(\n\t\t\t\t\"name:testNotificationWorkspace\",\n\t\t\t\t{\n\t\t\t\t\t\"testEvents\": Notifications({\n\t\t\t\t\t\tmissingAttendeeParam: (_id: number) => {},\n\t\t\t\t\t\tnonSerializableArg: (_attendee: Attendee, _fn: () => void) => {},\n\t\t\t\t\t\tokay: (_attendee: Attendee, _id: number) => {},\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t);\n\n\t\t\t// Verify\n\t\t\tassert.notEqual(notificationsWorkspace.notifications.testEvents, undefined);\n\t\t\tassertIdenticalTypes(\n\t\t\t\tnotificationsWorkspace.notifications.testEvents,\n\t\t\t\tcreateInstanceOf<NotificationsManager<{ okay: (id: number) => void }>>(),\n\t\t\t);\n\t\t});\n\n\t\tit(\"emit.broadcast sends broadcast signal\", async () => {\n\t\t\t// Setup\n\t\t\tconst notificationsWorkspace = presence.notifications.getWorkspace(\n\t\t\t\t\"name:testNotificationWorkspace\",\n\t\t\t\t{\n\t\t\t\t\t\"testEvents\": Notifications({\n\t\t\t\t\t\tnewId: (_attendee: Attendee, _id: number) => {},\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tconst { testEvents } = notificationsWorkspace.notifications;\n\n\t\t\tclock.tick(10);\n\n\t\t\truntime.signalsExpected.push([\n\t\t\t\t{\n\t\t\t\t\ttype: \"Pres:DatastoreUpdate\",\n\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\"sendTimestamp\": clock.now,\n\t\t\t\t\t\t\"avgLatency\": 10,\n\t\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\t\"system:presence\": {\n\t\t\t\t\t\t\t\t\"clientToSessionId\": {\n\t\t\t\t\t\t\t\t\t[initialLocalClientConnectionId]: {\n\t\t\t\t\t\t\t\t\t\t\"rev\": 0,\n\t\t\t\t\t\t\t\t\t\t\"timestamp\": initialTime,\n\t\t\t\t\t\t\t\t\t\t\"value\": localAttendeeId,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"n:name:testNotificationWorkspace\": {\n\t\t\t\t\t\t\t\t\"testEvents\": {\n\t\t\t\t\t\t\t\t\t[localAttendeeId]: {\n\t\t\t\t\t\t\t\t\t\t\"rev\": 0,\n\t\t\t\t\t\t\t\t\t\t\"timestamp\": 0,\n\t\t\t\t\t\t\t\t\t\t\"value\": toOpaqueJson({ \"name\": \"newId\", \"args\": [42] }),\n\t\t\t\t\t\t\t\t\t\t\"ignoreUnmonitored\": true,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t]);\n\n\t\t\t// Act & Verify\n\t\t\ttestEvents.emit.broadcast(\"newId\", 42);\n\n\t\t\tassertFinalExpectations(runtime, logger);\n\t\t});\n\n\t\t// TODO: Implement `unicast` method in NotificationsManager and in supporting code.\n\t\tit.skip(\"emit.unicast sends directed signal\", async () => {\n\t\t\t// Setup\n\t\t\tconst notificationsWorkspace = presence.notifications.getWorkspace(\n\t\t\t\t\"name:testNotificationWorkspace\",\n\t\t\t\t{\n\t\t\t\t\t\"testEvents\": Notifications({\n\t\t\t\t\t\tnewId: (_attendee: Attendee, _id: number) => {},\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tconst { testEvents } = notificationsWorkspace.notifications;\n\n\t\t\tclock.tick(10);\n\n\t\t\truntime.signalsExpected.push([\n\t\t\t\t{\n\t\t\t\t\ttype: \"Pres:DatastoreUpdate\",\n\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\"sendTimestamp\": clock.now,\n\t\t\t\t\t\t\"avgLatency\": 10,\n\t\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\t\"system:presence\": {\n\t\t\t\t\t\t\t\t\"clientToSessionId\": {\n\t\t\t\t\t\t\t\t\t[initialLocalClientConnectionId]: {\n\t\t\t\t\t\t\t\t\t\t\"rev\": 0,\n\t\t\t\t\t\t\t\t\t\t\"timestamp\": initialTime,\n\t\t\t\t\t\t\t\t\t\t\"value\": localAttendeeId,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"n:name:testNotificationWorkspace\": {\n\t\t\t\t\t\t\t\t\"testEvents\": {\n\t\t\t\t\t\t\t\t\t[localAttendeeId]: {\n\t\t\t\t\t\t\t\t\t\t\"rev\": 0,\n\t\t\t\t\t\t\t\t\t\t\"timestamp\": 0,\n\t\t\t\t\t\t\t\t\t\t\"value\": toOpaqueJson({ \"name\": \"newId\", \"args\": [42] }),\n\t\t\t\t\t\t\t\t\t\t\"ignoreUnmonitored\": true,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t// Targeting self for simplicity\n\t\t\t\t\ttargetClientId: initialLocalClientConnectionId,\n\t\t\t\t},\n\t\t\t]);\n\n\t\t\t// Act & Verify\n\t\t\ttestEvents.emit.unicast(\"newId\", presence.attendees.getMyself(), 42);\n\n\t\t\tassertFinalExpectations(runtime, logger);\n\t\t});\n\n\t\tit(\"raises named event when notification is received\", async () => {\n\t\t\ttype EventCalls = { attendee: Attendee; id: number }[];\n\t\t\tconst eventHandlerCalls = {\n\t\t\t\toriginal: [] as EventCalls,\n\t\t\t\tsecondary: [] as EventCalls,\n\t\t\t\ttertiary: [] as EventCalls,\n\t\t\t};\n\n\t\t\tfunction originalEventHandler(attendee: Attendee, id: number): void {\n\t\t\t\tassert.equal(attendee.attendeeId, attendeeId3);\n\t\t\t\tassert.equal(id, 42);\n\t\t\t\teventHandlerCalls.original.push({ attendee, id });\n\t\t\t}\n\n\t\t\tconst notificationsWorkspace = presence.notifications.getWorkspace(\n\t\t\t\t\"name:testNotificationWorkspace\",\n\t\t\t\t{\n\t\t\t\t\t\"testEvents\": Notifications({\n\t\t\t\t\t\tnewId: originalEventHandler,\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tconst { testEvents } = notificationsWorkspace.notifications;\n\n\t\t\ttestEvents.events.on(\"unattendedNotification\", (name) => {\n\t\t\t\tfail(`Unexpected unattendedNotification: ${name}`);\n\t\t\t});\n\n\t\t\tconst disconnectFunctions = [\n\t\t\t\ttestEvents.notifications.on(\"newId\", (attendee: Attendee, id: number) => {\n\t\t\t\t\teventHandlerCalls.secondary.push({ attendee, id });\n\t\t\t\t}),\n\t\t\t\ttestEvents.notifications.on(\"newId\", (attendee: Attendee, id: number) => {\n\t\t\t\t\teventHandlerCalls.tertiary.push({ attendee, id });\n\t\t\t\t}),\n\t\t\t];\n\n\t\t\t// Processing this signal should trigger the testEvents.newId event listeners\n\t\t\tprocessSignal(\n\t\t\t\t[],\n\t\t\t\t{\n\t\t\t\t\ttype: \"Pres:DatastoreUpdate\",\n\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\"sendTimestamp\": 1020,\n\t\t\t\t\t\t\"avgLatency\": 10,\n\t\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\t\"system:presence\": {\n\t\t\t\t\t\t\t\t\"clientToSessionId\": {\n\t\t\t\t\t\t\t\t\t[connectionId3]: { \"rev\": 0, \"timestamp\": 1000, \"value\": attendeeId3 },\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"n:name:testNotificationWorkspace\": {\n\t\t\t\t\t\t\t\t\"testEvents\": {\n\t\t\t\t\t\t\t\t\t[attendeeId3]: {\n\t\t\t\t\t\t\t\t\t\t\"rev\": 0,\n\t\t\t\t\t\t\t\t\t\t\"timestamp\": 0,\n\t\t\t\t\t\t\t\t\t\t\"value\": toOpaqueJson({ \"name\": \"newId\", \"args\": [42] }),\n\t\t\t\t\t\t\t\t\t\t\"ignoreUnmonitored\": true,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tclientId: \"client3\",\n\t\t\t\t},\n\t\t\t\tfalse,\n\t\t\t);\n\n\t\t\tassert(\n\t\t\t\teventHandlerCalls.original.length === 1,\n\t\t\t\t`original event handler was called ${eventHandlerCalls.original.length} times; expected 1`,\n\t\t\t);\n\t\t\tassert(\n\t\t\t\teventHandlerCalls.secondary.length === 1,\n\t\t\t\t`secondary event handler was called ${eventHandlerCalls.secondary.length} times; expected 1`,\n\t\t\t);\n\t\t\tassert(\n\t\t\t\teventHandlerCalls.tertiary.length === 1,\n\t\t\t\t`secondary event handler was called ${eventHandlerCalls.tertiary.length} times; expected 1`,\n\t\t\t);\n\n\t\t\t// Cleanup\n\t\t\tfor (const disconnect of disconnectFunctions) {\n\t\t\t\tdisconnect();\n\t\t\t}\n\t\t});\n\n\t\tit(\"raises `unattendedEvent` event when unrecognized notification is received\", async () => {\n\t\t\tlet unattendedEventCalled = false;\n\n\t\t\tconst notificationsWorkspace = presence.notifications.getWorkspace(\n\t\t\t\t\"name:testNotificationWorkspace\",\n\t\t\t\t{\n\t\t\t\t\t\"testEvents\": Notifications({\n\t\t\t\t\t\tnewId: (attendee: Attendee, id: number) => {\n\t\t\t\t\t\t\tfail(`Unexpected newId event`);\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tconst { testEvents } = notificationsWorkspace.notifications;\n\n\t\t\ttestEvents.events.on(\"unattendedNotification\", (name, sender, ...content) => {\n\t\t\t\tassert.equal(name, \"oldId\");\n\t\t\t\tassert.equal(sender.attendeeId, attendeeId3);\n\t\t\t\tassert.deepEqual(content, [41]);\n\t\t\t\tassert(!unattendedEventCalled);\n\t\t\t\tunattendedEventCalled = true;\n\t\t\t});\n\n\t\t\t// Processing this signal should trigger the testEvents.newId event listeners\n\t\t\tprocessSignal(\n\t\t\t\t[],\n\t\t\t\t{\n\t\t\t\t\ttype: \"Pres:DatastoreUpdate\",\n\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\"sendTimestamp\": 1020,\n\t\t\t\t\t\t\"avgLatency\": 10,\n\t\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\t\"system:presence\": {\n\t\t\t\t\t\t\t\t\"clientToSessionId\": {\n\t\t\t\t\t\t\t\t\t[connectionId3]: { \"rev\": 0, \"timestamp\": 1000, \"value\": attendeeId3 },\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"n:name:testNotificationWorkspace\": {\n\t\t\t\t\t\t\t\t\"testEvents\": {\n\t\t\t\t\t\t\t\t\t[attendeeId3]: {\n\t\t\t\t\t\t\t\t\t\t\"rev\": 0,\n\t\t\t\t\t\t\t\t\t\t\"timestamp\": 0,\n\t\t\t\t\t\t\t\t\t\t\"value\": toOpaqueJson({ \"name\": \"oldId\", \"args\": [41] }),\n\t\t\t\t\t\t\t\t\t\t\"ignoreUnmonitored\": true,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tclientId: \"client3\",\n\t\t\t\t},\n\t\t\t\tfalse,\n\t\t\t);\n\n\t\t\tassert(unattendedEventCalled, \"unattendedEvent not called\");\n\t\t});\n\n\t\tit(\"raises `unattendedEvent` event when recognized notification is received without listeners\", async () => {\n\t\t\tlet unattendedEventCalled = false;\n\n\t\t\tfunction newIdEventHandler(attendee: Attendee, id: number): void {\n\t\t\t\tfail(`Unexpected newId event`);\n\t\t\t}\n\n\t\t\tconst notificationsWorkspace = presence.notifications.getWorkspace(\n\t\t\t\t\"name:testNotificationWorkspace\",\n\t\t\t\t{\n\t\t\t\t\t\"testEvents\": Notifications({\n\t\t\t\t\t\tnewId: newIdEventHandler,\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tconst { testEvents } = notificationsWorkspace.notifications;\n\n\t\t\ttestEvents.events.on(\"unattendedNotification\", (name, sender, ...content) => {\n\t\t\t\tassert.equal(name, \"newId\");\n\t\t\t\tassert.equal(sender.attendeeId, attendeeId3);\n\t\t\t\tassert.deepEqual(content, [43]);\n\t\t\t\tassert(!unattendedEventCalled);\n\t\t\t\tunattendedEventCalled = true;\n\t\t\t});\n\n\t\t\ttestEvents.notifications.off(\"newId\", newIdEventHandler);\n\n\t\t\t// Processing this signal should trigger the testEvents.newId event listeners\n\t\t\tprocessSignal(\n\t\t\t\t[],\n\t\t\t\t{\n\t\t\t\t\ttype: \"Pres:DatastoreUpdate\",\n\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\"sendTimestamp\": 1020,\n\t\t\t\t\t\t\"avgLatency\": 10,\n\t\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\t\"system:presence\": {\n\t\t\t\t\t\t\t\t\"clientToSessionId\": {\n\t\t\t\t\t\t\t\t\t[connectionId3]: { \"rev\": 0, \"timestamp\": 1000, \"value\": attendeeId3 },\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"n:name:testNotificationWorkspace\": {\n\t\t\t\t\t\t\t\t\"testEvents\": {\n\t\t\t\t\t\t\t\t\t[attendeeId3]: {\n\t\t\t\t\t\t\t\t\t\t\"rev\": 0,\n\t\t\t\t\t\t\t\t\t\t\"timestamp\": 0,\n\t\t\t\t\t\t\t\t\t\t\"value\": toOpaqueJson({ \"name\": \"newId\", \"args\": [43] }),\n\t\t\t\t\t\t\t\t\t\t\"ignoreUnmonitored\": true,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tclientId: \"client3\",\n\t\t\t\t},\n\t\t\t\tfalse,\n\t\t\t);\n\n\t\t\tassert(unattendedEventCalled, \"unattendedEvent not called\");\n\t\t});\n\n\t\tit(\"removed listeners are not called when related notification is received\", async () => {\n\t\t\tlet originalEventHandlerCalled = false;\n\n\t\t\tfunction originalEventHandler(attendee: Attendee, id: number): void {\n\t\t\t\tassert.equal(attendee.attendeeId, attendeeId3);\n\t\t\t\tassert.equal(id, 44);\n\t\t\t\tassert.equal(originalEventHandlerCalled, false);\n\t\t\t\toriginalEventHandlerCalled = true;\n\t\t\t}\n\n\t\t\tconst notificationsWorkspace = presence.notifications.getWorkspace(\n\t\t\t\t\"name:testNotificationWorkspace\",\n\t\t\t\t{\n\t\t\t\t\t\"testEvents\": Notifications({\n\t\t\t\t\t\tnewId: originalEventHandler,\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tconst { testEvents } = notificationsWorkspace.notifications;\n\n\t\t\ttestEvents.events.on(\"unattendedNotification\", (name) => {\n\t\t\t\tfail(`Unexpected unattendedNotification: ${name}`);\n\t\t\t});\n\n\t\t\tconst disconnect = testEvents.notifications.on(\n\t\t\t\t\"newId\",\n\t\t\t\t(_attendee: Attendee, _id: number) => {\n\t\t\t\t\tfail(`Unexpected event raised on disconnected listener`);\n\t\t\t\t},\n\t\t\t);\n\t\t\t// Remove the listener\n\t\t\tdisconnect();\n\n\t\t\t// Act\n\t\t\tprocessSignal(\n\t\t\t\t[],\n\t\t\t\t{\n\t\t\t\t\ttype: \"Pres:DatastoreUpdate\",\n\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\"sendTimestamp\": 1020,\n\t\t\t\t\t\t\"avgLatency\": 10,\n\t\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\t\"system:presence\": {\n\t\t\t\t\t\t\t\t\"clientToSessionId\": {\n\t\t\t\t\t\t\t\t\t[connectionId3]: { \"rev\": 0, \"timestamp\": 1000, \"value\": attendeeId3 },\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"n:name:testNotificationWorkspace\": {\n\t\t\t\t\t\t\t\t\"testEvents\": {\n\t\t\t\t\t\t\t\t\t[attendeeId3]: {\n\t\t\t\t\t\t\t\t\t\t\"rev\": 0,\n\t\t\t\t\t\t\t\t\t\t\"timestamp\": 0,\n\t\t\t\t\t\t\t\t\t\t\"value\": toOpaqueJson({ \"name\": \"newId\", \"args\": [44] }),\n\t\t\t\t\t\t\t\t\t\t\"ignoreUnmonitored\": true,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tclientId: \"client3\",\n\t\t\t\t},\n\t\t\t\tfalse,\n\t\t\t);\n\n\t\t\t// Verify\n\t\t\tassert(originalEventHandlerCalled, \"originalEventHandler not called\");\n\t\t});\n\n\t\tit(\".presence provides Presence it was created under\", () => {\n\t\t\tconst notificationsWorkspace = presence.notifications.getWorkspace(\n\t\t\t\t\"name:testNotificationWorkspace\",\n\t\t\t\t{\n\t\t\t\t\t\"testEvents\": Notifications<{\n\t\t\t\t\t\tnewId: (id: number) => void;\n\t\t\t\t\t}>(\n\t\t\t\t\t\t// A default handler is not required\n\t\t\t\t\t\t{},\n\t\t\t\t\t),\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tassert.strictEqual(notificationsWorkspace.notifications.testEvents.presence, presence);\n\t\t\tassert.strictEqual(notificationsWorkspace.presence, presence);\n\t\t});\n\t});\n});\n\n// ---- test (example) code ----\n\n/**\n * Check that the code compiles.\n */\nexport function checkCompiles(): void {\n\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\tconst presence = {} as PresenceWithNotifications;\n\tpresence.notifications.getWorkspace(\"name:testNotifications\", {\n\t\ttestEvents: Notifications({\n\t\t\thotSpot: (_sender: Attendee, _: { x: number; y: number }): void => {},\n\t\t}),\n\t\t// @ts-expect-error - Notifications Workspace only permits NotificationsManagers\n\t\tcamera: StateFactory.latest({ local: { x: 0, y: 0, z: 0 } }),\n\t});\n}\n"]}
@@ -1,69 +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 { createPresenceManager } from "@fluid-internal/presence-runtime/internal/test";
7
- import { StateFactory } from "@fluid-internal/presence-runtime/states";
8
- import { addControlsTests } from "./broadcastControlsTests.js";
9
- import { MockEphemeralRuntime } from "./mockEphemeralRuntime.js";
10
- const testWorkspaceName = "name:testWorkspaceA";
11
- describe("Presence/States", () => {
12
- describe("StatesWorkspace", () => {
13
- /**
14
- * See {@link checkCompiles} below
15
- */
16
- it("API use compiles", () => { });
17
- addControlsTests((presence, controlSettings) => {
18
- return presence.states.getWorkspace(testWorkspaceName, {}, controlSettings);
19
- });
20
- it(".presence provides Presence it was created under", () => {
21
- const presence = createPresenceManager(new MockEphemeralRuntime());
22
- const states = presence.states.getWorkspace(testWorkspaceName, {
23
- obj: StateFactory.latest({ local: {} }),
24
- });
25
- assert.strictEqual(states.presence, presence);
26
- });
27
- });
28
- });
29
- // ---- test (example) code ----
30
- /**
31
- * Check that the code compiles.
32
- */
33
- export function checkCompiles() {
34
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
35
- const presence = {};
36
- const statesWorkspace = presence.states.getWorkspace("name:testWorkspaceA", {
37
- cursor: createValueManager({ x: 0, y: 0 }),
38
- // eslint-disable-next-line prefer-object-spread
39
- camera: Object.assign({ instanceBase: undefined }, () => ({
40
- value: { rev: 0, timestamp: Date.now(), value: { x: 0, y: 0, z: 0 } },
41
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
42
- manager: {},
43
- })),
44
- });
45
- // Workaround ts(2775): Assertions require every name in the call target to be declared with an explicit type annotation.
46
- const states = statesWorkspace;
47
- const initialCaret = { id: "", pos: 0 };
48
- states.add("caret", createValueManager(initialCaret));
49
- const statesProps = states.states;
50
- const fakeAdd = statesProps.camera.z + statesProps.cursor.x + statesProps.caret.pos;
51
- console.log(fakeAdd);
52
- // @ts-expect-error should error on typo detection
53
- console.log(states.curso); // error to highlight typo detection (proper typing in effect)
54
- // example of second add at existing key - results in union of types (should throw at runtime)
55
- states.add("caret", createValueManager({ dupe: 0 }));
56
- states.add("undefined",
57
- // @ts-expect-error should error non-optional undefined
58
- createValueManager({ undef: undefined }));
59
- states.add("undefOrNum",
60
- // @ts-expect-error should error on non-optional that may be undefined
61
- createValueManager({ undefOrNum: 4 }));
62
- // optional undefined is ok - though not recommended to actually specify such properties with
63
- // undefined values as the properties won't come back; they will be absent.
64
- states.add("optionalUndefined",
65
- // @ts-expect-error should error on exact optional property
66
- createValueManager({ undef: undefined }));
67
- states.add("optionalUndefinedPreferred", createValueManager({}));
68
- }
69
- //# sourceMappingURL=presenceStates.spec.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"presenceStates.spec.js","sourceRoot":"","sources":["../../../src/states/test/presenceStates.spec.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,IAAI,MAAM,EAAE,MAAM,aAAa,CAAC;AAQ/C,OAAO,EAAE,qBAAqB,EAAE,MAAM,gDAAgD,CAAC;AACvF,OAAO,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AAEvE,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEjE,MAAM,iBAAiB,GAAG,qBAAqB,CAAC;AAEhD,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAChC,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;QAChC;;WAEG;QACH,EAAE,CAAC,kBAAkB,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAEjC,gBAAgB,CAAC,CAAC,QAAQ,EAAE,eAAe,EAAE,EAAE;YAC9C,OAAO,QAAQ,CAAC,MAAM,CAAC,YAAY,CAAC,iBAAiB,EAAE,EAAE,EAAE,eAAe,CAAC,CAAC;QAC7E,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;YAC3D,MAAM,QAAQ,GAAG,qBAAqB,CAAC,IAAI,oBAAoB,EAAE,CAAC,CAAC;YACnE,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,YAAY,CAAC,iBAAiB,EAAE;gBAC9D,GAAG,EAAE,YAAY,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;aACvC,CAAC,CAAC;YACH,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC;AAeH,gCAAgC;AAEhC;;GAEG;AACH,MAAM,UAAU,aAAa;IAC5B,yEAAyE;IACzE,MAAM,QAAQ,GAAG,EAAc,CAAC;IAChC,MAAM,eAAe,GAAG,QAAQ,CAAC,MAAM,CAAC,YAAY,CAAC,qBAAqB,EAAE;QAC3E,MAAM,EAAE,kBAAkB,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;QAC1C,gDAAgD;QAChD,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,YAAY,EAAE,SAAyC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;YACzF,KAAK,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE;YACrE,yEAAyE;YACzE,OAAO,EAAE,EAA2E;SACpF,CAAC,CAAC;KACH,CAAC,CAAC;IACH,yHAAyH;IACzH,MAAM,MAAM,GAA2B,eAAe,CAAC;IAEvD,MAAM,YAAY,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;IACxC,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,kBAAkB,CAAC,YAAY,CAAC,CAAC,CAAC;IACtD,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC;IAElC,MAAM,OAAO,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC;IACpF,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAErB,kDAAkD;IAClD,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,8DAA8D;IAEzF,8FAA8F;IAC9F,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,kBAAkB,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAErD,MAAM,CAAC,GAAG,CACT,WAAW;IACX,uDAAuD;IACvD,kBAAkB,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CACxC,CAAC;IAEF,MAAM,CAAC,GAAG,CACT,YAAY;IACZ,sEAAsE;IACtE,kBAAkB,CAAmD,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC,CACvF,CAAC;IAEF,6FAA6F;IAC7F,2EAA2E;IAC3E,MAAM,CAAC,GAAG,CACT,mBAAmB;IACnB,2DAA2D;IAC3D,kBAAkB,CAA0C,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CACjF,CAAC;IACF,MAAM,CAAC,GAAG,CACT,4BAA4B,EAC5B,kBAAkB,CAAmD,EAAE,CAAC,CACxE,CAAC;AACH,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { strict as assert } from \"node:assert\";\n\nimport type { InternalPresenceTypes, Presence } from \"@fluid-internal/presence-definitions\";\nimport type {\n\tJsonDeserialized,\n\tJsonSerializable,\n} from \"@fluidframework/core-interfaces/internal/exposedUtilityTypes\";\n\nimport { createPresenceManager } from \"@fluid-internal/presence-runtime/internal/test\";\nimport { StateFactory } from \"@fluid-internal/presence-runtime/states\";\n\nimport { addControlsTests } from \"./broadcastControlsTests.js\";\nimport { MockEphemeralRuntime } from \"./mockEphemeralRuntime.js\";\n\nconst testWorkspaceName = \"name:testWorkspaceA\";\n\ndescribe(\"Presence/States\", () => {\n\tdescribe(\"StatesWorkspace\", () => {\n\t\t/**\n\t\t * See {@link checkCompiles} below\n\t\t */\n\t\tit(\"API use compiles\", () => {});\n\n\t\taddControlsTests((presence, controlSettings) => {\n\t\t\treturn presence.states.getWorkspace(testWorkspaceName, {}, controlSettings);\n\t\t});\n\n\t\tit(\".presence provides Presence it was created under\", () => {\n\t\t\tconst presence = createPresenceManager(new MockEphemeralRuntime());\n\t\t\tconst states = presence.states.getWorkspace(testWorkspaceName, {\n\t\t\t\tobj: StateFactory.latest({ local: {} }),\n\t\t\t});\n\t\t\tassert.strictEqual(states.presence, presence);\n\t\t});\n\t});\n});\n\ndeclare function createValueManager<T, Key extends string>(\n\tinitial: JsonSerializable<T>,\n): { instanceBase: new () => unknown } & ((\n\tkey: Key,\n\tdatastoreHandle: InternalPresenceTypes.StateDatastoreHandle<\n\t\tKey,\n\t\tInternalPresenceTypes.ValueRequiredState<T>\n\t>,\n) => {\n\tvalue: InternalPresenceTypes.ValueRequiredState<T>;\n\tmanager: InternalPresenceTypes.StateValue<JsonDeserialized<T>>;\n});\n\n// ---- test (example) code ----\n\n/**\n * Check that the code compiles.\n */\nexport function checkCompiles(): void {\n\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\tconst presence = {} as Presence;\n\tconst statesWorkspace = presence.states.getWorkspace(\"name:testWorkspaceA\", {\n\t\tcursor: createValueManager({ x: 0, y: 0 }),\n\t\t// eslint-disable-next-line prefer-object-spread\n\t\tcamera: Object.assign({ instanceBase: undefined as unknown as new () => unknown }, () => ({\n\t\t\tvalue: { rev: 0, timestamp: Date.now(), value: { x: 0, y: 0, z: 0 } },\n\t\t\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\t\t\tmanager: {} as InternalPresenceTypes.StateValue<{ x: number; y: number; z: number }>,\n\t\t})),\n\t});\n\t// Workaround ts(2775): Assertions require every name in the call target to be declared with an explicit type annotation.\n\tconst states: typeof statesWorkspace = statesWorkspace;\n\n\tconst initialCaret = { id: \"\", pos: 0 };\n\tstates.add(\"caret\", createValueManager(initialCaret));\n\tconst statesProps = states.states;\n\n\tconst fakeAdd = statesProps.camera.z + statesProps.cursor.x + statesProps.caret.pos;\n\tconsole.log(fakeAdd);\n\n\t// @ts-expect-error should error on typo detection\n\tconsole.log(states.curso); // error to highlight typo detection (proper typing in effect)\n\n\t// example of second add at existing key - results in union of types (should throw at runtime)\n\tstates.add(\"caret\", createValueManager({ dupe: 0 }));\n\n\tstates.add(\n\t\t\"undefined\",\n\t\t// @ts-expect-error should error non-optional undefined\n\t\tcreateValueManager({ undef: undefined }),\n\t);\n\n\tstates.add(\n\t\t\"undefOrNum\",\n\t\t// @ts-expect-error should error on non-optional that may be undefined\n\t\tcreateValueManager<{ undefOrNum: undefined | number }, \"undefOrNum\">({ undefOrNum: 4 }),\n\t);\n\n\t// optional undefined is ok - though not recommended to actually specify such properties with\n\t// undefined values as the properties won't come back; they will be absent.\n\tstates.add(\n\t\t\"optionalUndefined\",\n\t\t// @ts-expect-error should error on exact optional property\n\t\tcreateValueManager<{ undef?: number }, \"optionalUndefined\">({ undef: undefined }),\n\t);\n\tstates.add(\n\t\t\"optionalUndefinedPreferred\",\n\t\tcreateValueManager<{ undef?: number }, \"optionalUndefinedPreferred\">({}),\n\t);\n}\n"]}