@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,244 +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 { EventAndErrorTrackingLogger } from "@fluidframework/test-utils/internal";
7
- import { describe, it, after, afterEach, before, beforeEach } from "mocha";
8
- import { useFakeTimers } from "sinon";
9
- import { broadcastJoinResponseDelaysMs } from "@fluid-internal/presence-runtime/internal/test";
10
- import { StateFactory } from "@fluid-internal/presence-runtime/states";
11
- import { toOpaqueJson } from "@fluid-internal/presence-runtime/utils";
12
- import { MockEphemeralRuntime } from "../mockEphemeralRuntime.js";
13
- import { assertFinalExpectations, attendeeId1, localAttendeeId, connectionId1, initialLocalClientConnectionId, createSpecificAttendeeId, createSpiedValidator, generateBasicClientJoin, prepareConnectedPresence, } from "../testUtils.js";
14
- describe("Presence/States", () => {
15
- describe("Runtime schema validation", () => {
16
- const afterCleanUp = [];
17
- const initialTime = 500;
18
- const attendee1ValueRevisionTimestamp = 600;
19
- const testStartTime = 1010;
20
- let localAttendee1ValueRevisionTimestamp;
21
- let clock;
22
- let logger;
23
- let presence;
24
- let processSignal;
25
- let runtime;
26
- before(async () => {
27
- clock = useFakeTimers();
28
- });
29
- beforeEach(() => {
30
- logger = new EventAndErrorTrackingLogger();
31
- runtime = new MockEphemeralRuntime(logger);
32
- clock.setSystemTime(initialTime);
33
- let localAvgLatency;
34
- ({ presence, processSignal, localAvgLatency } = prepareConnectedPresence(runtime, localAttendeeId, initialLocalClientConnectionId, clock, logger));
35
- // Note that while the initialTime was set to 500, the prepareConnectedPresence call advances
36
- // it. Set a consistent start time for all tests.
37
- const deltaToStart = testStartTime - clock.now;
38
- assert(deltaToStart >= 10);
39
- clock.tick(deltaToStart - 10);
40
- // Process remote client update signal (attendeeId-1 is then part of local client's known session).
41
- const attendee1UpdateSendTimestamp = deltaToStart - 20;
42
- const attendee1AvgLatency = 20;
43
- const attendee1ToLocalTimeDelta = clock.now - (localAvgLatency + attendee1AvgLatency + attendee1UpdateSendTimestamp);
44
- localAttendee1ValueRevisionTimestamp =
45
- attendee1ValueRevisionTimestamp + attendee1ToLocalTimeDelta;
46
- processSignal([], {
47
- type: "Pres:DatastoreUpdate",
48
- content: {
49
- sendTimestamp: attendee1UpdateSendTimestamp,
50
- avgLatency: attendee1AvgLatency,
51
- data: {
52
- "system:presence": {
53
- "clientToSessionId": {
54
- "client1": {
55
- "rev": 0,
56
- "timestamp": initialTime + 40,
57
- "value": attendeeId1,
58
- },
59
- },
60
- },
61
- "s:name:testWorkspace": {
62
- "latest": {
63
- [attendeeId1]: {
64
- "rev": 1,
65
- "timestamp": attendee1ValueRevisionTimestamp,
66
- "value": toOpaqueJson({ x: 1, y: 1, z: 1 }),
67
- },
68
- },
69
- "latestMap": {
70
- [attendeeId1]: {
71
- "rev": 1,
72
- "items": {
73
- "key1": {
74
- "rev": 1,
75
- "timestamp": attendee1ValueRevisionTimestamp,
76
- "value": toOpaqueJson({ a: 1, b: 1 }),
77
- },
78
- "key2": {
79
- "rev": 1,
80
- "timestamp": attendee1ValueRevisionTimestamp,
81
- // out of schema value
82
- "value": toOpaqueJson({ b: 1, d: 1 }),
83
- },
84
- },
85
- },
86
- },
87
- },
88
- },
89
- },
90
- clientId: "client1",
91
- }, false);
92
- // Pass a little time (to mimic reality)
93
- clock.tick(10);
94
- });
95
- afterEach(function (done) {
96
- clock.reset();
97
- // If the test passed so far, check final expectations.
98
- if (this.currentTest?.state === "passed") {
99
- assertFinalExpectations(runtime, logger);
100
- }
101
- for (const cleanUp of afterCleanUp) {
102
- cleanUp();
103
- }
104
- afterCleanUp.length = 0;
105
- done();
106
- });
107
- after(() => {
108
- clock.restore();
109
- });
110
- describe("response to Join signal", () => {
111
- it("does not contain validation metadata for remote clients", () => {
112
- // Setup
113
- // Check Join response without active validators
114
- const attendeeId4 = createSpecificAttendeeId("attendeeId-4");
115
- const connectionId4 = "client4";
116
- const client4JoinTime = clock.now - 50;
117
- const newAttendeeSignal = generateBasicClientJoin(client4JoinTime, {
118
- averageLatency: 50,
119
- attendeeId: attendeeId4,
120
- clientConnectionId: connectionId4,
121
- updateProviders: [initialLocalClientConnectionId],
122
- });
123
- const expectedSetupJoinResponse = {
124
- type: "Pres:DatastoreUpdate",
125
- content: {
126
- "avgLatency": 10,
127
- "data": {
128
- "system:presence": {
129
- "clientToSessionId": {
130
- [initialLocalClientConnectionId]: {
131
- "rev": 0,
132
- "timestamp": initialTime,
133
- "value": localAttendeeId,
134
- },
135
- [connectionId1]: {
136
- "rev": 0,
137
- "timestamp": initialTime + 40,
138
- "value": attendeeId1,
139
- },
140
- [connectionId4]: {
141
- "rev": 0,
142
- "timestamp": client4JoinTime,
143
- "value": attendeeId4,
144
- },
145
- },
146
- },
147
- "s:name:testWorkspace": {
148
- "latest": {
149
- [attendeeId1]: {
150
- "rev": 1,
151
- "timestamp": localAttendee1ValueRevisionTimestamp,
152
- "value": toOpaqueJson({ x: 1, y: 1, z: 1 }),
153
- },
154
- },
155
- "latestMap": {
156
- [attendeeId1]: {
157
- "rev": 1,
158
- "items": {
159
- "key1": {
160
- "rev": 1,
161
- "timestamp": localAttendee1ValueRevisionTimestamp,
162
- "value": toOpaqueJson({ a: 1, b: 1 }),
163
- },
164
- "key2": {
165
- "rev": 1,
166
- "timestamp": localAttendee1ValueRevisionTimestamp,
167
- "value": toOpaqueJson({ b: 1, d: 1 }),
168
- },
169
- },
170
- },
171
- },
172
- },
173
- },
174
- "isComplete": true,
175
- "joinResponseFor": [connectionId4],
176
- "sendTimestamp": clock.now + broadcastJoinResponseDelaysMs.namedResponder,
177
- },
178
- };
179
- {
180
- runtime.signalsExpected.push([expectedSetupJoinResponse]);
181
- processSignal([], newAttendeeSignal, false);
182
- clock.tick(broadcastJoinResponseDelaysMs.namedResponder);
183
- }
184
- // Pass a little time (to distinguish between signals)
185
- clock.tick(10);
186
- // Create State objects with validators
187
- const workspaceSetupTime = clock.now;
188
- const point3DValidatorFunction = createSpiedValidator((d) => {
189
- return typeof d === "object" ? d : undefined;
190
- });
191
- const statesWorkspace = presence.states.getWorkspace("name:testWorkspace", {
192
- latest: StateFactory.latest({
193
- local: { x: 0, y: 0, z: 0 },
194
- validator: point3DValidatorFunction,
195
- settings: {
196
- // To prevent sending messages ahead of full broadcast from
197
- // join below, set the allowable latency to twice expected
198
- // join response time.
199
- allowableUpdateLatencyMs: 2 * broadcastJoinResponseDelaysMs.namedResponder,
200
- },
201
- }),
202
- });
203
- const latest = statesWorkspace.states.latest;
204
- const attendee1 = presence.attendees.getAttendee(attendeeId1);
205
- latest.getRemote(attendee1)?.value();
206
- const originalJoinResponseData = expectedSetupJoinResponse.content.data;
207
- const expectedJoinResponse = {
208
- type: "Pres:DatastoreUpdate",
209
- content: {
210
- "avgLatency": 10,
211
- "data": {
212
- "system:presence": {
213
- "clientToSessionId": {
214
- ...originalJoinResponseData["system:presence"].clientToSessionId,
215
- },
216
- },
217
- "s:name:testWorkspace": {
218
- "latest": {
219
- ...originalJoinResponseData["s:name:testWorkspace"].latest,
220
- [localAttendeeId]: {
221
- "rev": 0,
222
- "timestamp": workspaceSetupTime,
223
- "value": toOpaqueJson({ x: 0, y: 0, z: 0 }),
224
- },
225
- },
226
- "latestMap": {
227
- ...originalJoinResponseData["s:name:testWorkspace"].latestMap,
228
- },
229
- },
230
- },
231
- "isComplete": true,
232
- "joinResponseFor": [connectionId4],
233
- "sendTimestamp": clock.now + broadcastJoinResponseDelaysMs.namedResponder,
234
- },
235
- };
236
- runtime.signalsExpected.push([expectedJoinResponse]);
237
- // Act & Verify - resend new attendee Join signal
238
- processSignal([], newAttendeeSignal, false);
239
- clock.tick(broadcastJoinResponseDelaysMs.namedResponder);
240
- });
241
- });
242
- });
243
- });
244
- //# sourceMappingURL=protocol.spec.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"protocol.spec.js","sourceRoot":"","sources":["../../../../src/states/test/schemaValidation/protocol.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 } from \"node:assert\";\n\nimport type { PresenceWithNotifications } from \"@fluid-internal/presence-definitions\";\nimport { EventAndErrorTrackingLogger } from \"@fluidframework/test-utils/internal\";\nimport { describe, it, after, afterEach, before, beforeEach } from \"mocha\";\nimport { useFakeTimers, type SinonFakeTimers } from \"sinon\";\n\nimport type { OutboundDatastoreUpdateMessage } from \"@fluid-internal/presence-runtime/internal/test\";\nimport { broadcastJoinResponseDelaysMs } from \"@fluid-internal/presence-runtime/internal/test\";\nimport { 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\tattendeeId1,\n\tlocalAttendeeId,\n\tconnectionId1,\n\tinitialLocalClientConnectionId,\n\tcreateSpecificAttendeeId,\n\tcreateSpiedValidator,\n\tgenerateBasicClientJoin,\n\tprepareConnectedPresence,\n} from \"../testUtils.js\";\n\n/**\n * Workspace updates\n */\ninterface Point3D {\n\tx: number;\n\ty: number;\n\tz: number;\n}\n\ndescribe(\"Presence/States\", () => {\n\tdescribe(\"Runtime schema validation\", () => {\n\t\tconst afterCleanUp: (() => void)[] = [];\n\t\tconst initialTime = 500;\n\t\tconst attendee1ValueRevisionTimestamp = 600;\n\t\tconst testStartTime = 1010;\n\t\tlet localAttendee1ValueRevisionTimestamp: number;\n\n\t\tlet clock: SinonFakeTimers;\n\t\tlet logger: EventAndErrorTrackingLogger;\n\t\tlet presence: PresenceWithNotifications;\n\t\tlet processSignal: ProcessSignalFunction;\n\t\tlet runtime: MockEphemeralRuntime;\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\t\t\tclock.setSystemTime(initialTime);\n\n\t\t\tlet localAvgLatency: number;\n\t\t\t({ presence, processSignal, localAvgLatency } = 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\n\t\t\t// Note that while the initialTime was set to 500, the prepareConnectedPresence call advances\n\t\t\t// it. Set a consistent start time for all tests.\n\t\t\tconst deltaToStart = testStartTime - clock.now;\n\t\t\tassert(deltaToStart >= 10);\n\t\t\tclock.tick(deltaToStart - 10);\n\n\t\t\t// Process remote client update signal (attendeeId-1 is then part of local client's known session).\n\t\t\tconst attendee1UpdateSendTimestamp = deltaToStart - 20;\n\t\t\tconst attendee1AvgLatency = 20;\n\t\t\tconst attendee1ToLocalTimeDelta =\n\t\t\t\tclock.now - (localAvgLatency + attendee1AvgLatency + attendee1UpdateSendTimestamp);\n\t\t\tlocalAttendee1ValueRevisionTimestamp =\n\t\t\t\tattendee1ValueRevisionTimestamp + attendee1ToLocalTimeDelta;\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\tsendTimestamp: attendee1UpdateSendTimestamp,\n\t\t\t\t\t\tavgLatency: attendee1AvgLatency,\n\t\t\t\t\t\tdata: {\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\"client1\": {\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 + 40,\n\t\t\t\t\t\t\t\t\t\t\"value\": attendeeId1,\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\"s:name:testWorkspace\": {\n\t\t\t\t\t\t\t\t\"latest\": {\n\t\t\t\t\t\t\t\t\t[attendeeId1]: {\n\t\t\t\t\t\t\t\t\t\t\"rev\": 1,\n\t\t\t\t\t\t\t\t\t\t\"timestamp\": attendee1ValueRevisionTimestamp,\n\t\t\t\t\t\t\t\t\t\t\"value\": toOpaqueJson({ x: 1, y: 1, z: 1 }),\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\t\"latestMap\": {\n\t\t\t\t\t\t\t\t\t[attendeeId1]: {\n\t\t\t\t\t\t\t\t\t\t\"rev\": 1,\n\t\t\t\t\t\t\t\t\t\t\"items\": {\n\t\t\t\t\t\t\t\t\t\t\t\"key1\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"rev\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\t\"timestamp\": attendee1ValueRevisionTimestamp,\n\t\t\t\t\t\t\t\t\t\t\t\t\"value\": toOpaqueJson({ a: 1, b: 1 }),\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"key2\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"rev\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\t\"timestamp\": attendee1ValueRevisionTimestamp,\n\t\t\t\t\t\t\t\t\t\t\t\t// out of schema value\n\t\t\t\t\t\t\t\t\t\t\t\t\"value\": toOpaqueJson({ b: 1, d: 1 }),\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\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: \"client1\",\n\t\t\t\t},\n\t\t\t\tfalse,\n\t\t\t);\n\n\t\t\t// Pass a little time (to mimic reality)\n\t\t\tclock.tick(10);\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\n\t\t\tfor (const cleanUp of afterCleanUp) {\n\t\t\t\tcleanUp();\n\t\t\t}\n\t\t\tafterCleanUp.length = 0;\n\t\t\tdone();\n\t\t});\n\n\t\tafter(() => {\n\t\t\tclock.restore();\n\t\t});\n\n\t\tdescribe(\"response to Join signal\", () => {\n\t\t\tit(\"does not contain validation metadata for remote clients\", () => {\n\t\t\t\t// Setup\n\n\t\t\t\t// Check Join response without active validators\n\t\t\t\tconst attendeeId4 = createSpecificAttendeeId(\"attendeeId-4\");\n\t\t\t\tconst connectionId4 = \"client4\";\n\t\t\t\tconst client4JoinTime = clock.now - 50;\n\t\t\t\tconst newAttendeeSignal = generateBasicClientJoin(client4JoinTime, {\n\t\t\t\t\taverageLatency: 50,\n\t\t\t\t\tattendeeId: attendeeId4,\n\t\t\t\t\tclientConnectionId: connectionId4,\n\t\t\t\t\tupdateProviders: [initialLocalClientConnectionId],\n\t\t\t\t});\n\t\t\t\tconst expectedSetupJoinResponse = {\n\t\t\t\t\ttype: \"Pres:DatastoreUpdate\",\n\t\t\t\t\tcontent: {\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\t[connectionId1]: {\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 + 40,\n\t\t\t\t\t\t\t\t\t\t\"value\": attendeeId1,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t[connectionId4]: {\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\": client4JoinTime,\n\t\t\t\t\t\t\t\t\t\t\"value\": attendeeId4,\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\"s:name:testWorkspace\": {\n\t\t\t\t\t\t\t\t\"latest\": {\n\t\t\t\t\t\t\t\t\t[attendeeId1]: {\n\t\t\t\t\t\t\t\t\t\t\"rev\": 1,\n\t\t\t\t\t\t\t\t\t\t\"timestamp\": localAttendee1ValueRevisionTimestamp,\n\t\t\t\t\t\t\t\t\t\t\"value\": toOpaqueJson({ x: 1, y: 1, z: 1 }),\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\t\"latestMap\": {\n\t\t\t\t\t\t\t\t\t[attendeeId1]: {\n\t\t\t\t\t\t\t\t\t\t\"rev\": 1,\n\t\t\t\t\t\t\t\t\t\t\"items\": {\n\t\t\t\t\t\t\t\t\t\t\t\"key1\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"rev\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\t\"timestamp\": localAttendee1ValueRevisionTimestamp,\n\t\t\t\t\t\t\t\t\t\t\t\t\"value\": toOpaqueJson({ a: 1, b: 1 }),\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"key2\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"rev\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\t\"timestamp\": localAttendee1ValueRevisionTimestamp,\n\t\t\t\t\t\t\t\t\t\t\t\t\"value\": toOpaqueJson({ b: 1, d: 1 }),\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\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\t\"isComplete\": true,\n\t\t\t\t\t\t\"joinResponseFor\": [connectionId4],\n\t\t\t\t\t\t\"sendTimestamp\": clock.now + broadcastJoinResponseDelaysMs.namedResponder,\n\t\t\t\t\t},\n\t\t\t\t} as const satisfies OutboundDatastoreUpdateMessage;\n\t\t\t\t{\n\t\t\t\t\truntime.signalsExpected.push([expectedSetupJoinResponse]);\n\t\t\t\t\tprocessSignal([], newAttendeeSignal, false);\n\t\t\t\t\tclock.tick(broadcastJoinResponseDelaysMs.namedResponder);\n\t\t\t\t}\n\t\t\t\t// Pass a little time (to distinguish between signals)\n\t\t\t\tclock.tick(10);\n\n\t\t\t\t// Create State objects with validators\n\t\t\t\tconst workspaceSetupTime = clock.now;\n\t\t\t\tconst point3DValidatorFunction = createSpiedValidator<Point3D>((d: unknown) => {\n\t\t\t\t\treturn typeof d === \"object\" ? (d as Point3D) : undefined;\n\t\t\t\t});\n\t\t\t\tconst statesWorkspace = presence.states.getWorkspace(\"name:testWorkspace\", {\n\t\t\t\t\tlatest: StateFactory.latest({\n\t\t\t\t\t\tlocal: { x: 0, y: 0, z: 0 },\n\t\t\t\t\t\tvalidator: point3DValidatorFunction,\n\t\t\t\t\t\tsettings: {\n\t\t\t\t\t\t\t// To prevent sending messages ahead of full broadcast from\n\t\t\t\t\t\t\t// join below, set the allowable latency to twice expected\n\t\t\t\t\t\t\t// join response time.\n\t\t\t\t\t\t\tallowableUpdateLatencyMs: 2 * broadcastJoinResponseDelaysMs.namedResponder,\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t});\n\t\t\t\tconst latest = statesWorkspace.states.latest;\n\t\t\t\tconst attendee1 = presence.attendees.getAttendee(attendeeId1);\n\n\t\t\t\tlatest.getRemote(attendee1)?.value();\n\n\t\t\t\tconst originalJoinResponseData = expectedSetupJoinResponse.content.data;\n\t\t\t\tconst expectedJoinResponse = {\n\t\t\t\t\ttype: \"Pres:DatastoreUpdate\",\n\t\t\t\t\tcontent: {\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...originalJoinResponseData[\"system:presence\"].clientToSessionId,\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\"s:name:testWorkspace\": {\n\t\t\t\t\t\t\t\t\"latest\": {\n\t\t\t\t\t\t\t\t\t...originalJoinResponseData[\"s:name:testWorkspace\"].latest,\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\": workspaceSetupTime,\n\t\t\t\t\t\t\t\t\t\t\"value\": toOpaqueJson({ x: 0, y: 0, z: 0 }),\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\t\"latestMap\": {\n\t\t\t\t\t\t\t\t\t...originalJoinResponseData[\"s:name:testWorkspace\"].latestMap,\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\t\"isComplete\": true,\n\t\t\t\t\t\t\"joinResponseFor\": [connectionId4],\n\t\t\t\t\t\t\"sendTimestamp\": clock.now + broadcastJoinResponseDelaysMs.namedResponder,\n\t\t\t\t\t},\n\t\t\t\t} as const satisfies OutboundDatastoreUpdateMessage;\n\t\t\t\truntime.signalsExpected.push([expectedJoinResponse]);\n\n\t\t\t\t// Act & Verify - resend new attendee Join signal\n\t\t\t\tprocessSignal([], newAttendeeSignal, false);\n\t\t\t\tclock.tick(broadcastJoinResponseDelaysMs.namedResponder);\n\t\t\t});\n\t\t});\n\t});\n});\n"]}