@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.
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/runtime/extension/containerPresence.d.ts +1 -1
- package/dist/runtime/presenceDatastoreManager.d.ts +2 -2
- package/dist/runtime/presenceDatastoreManager.d.ts.map +1 -1
- package/dist/runtime/presenceDatastoreManager.js.map +1 -1
- package/dist/runtime/presenceManager.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/runtime/extension/containerPresence.d.ts +1 -1
- package/lib/runtime/presenceDatastoreManager.d.ts +2 -2
- package/lib/runtime/presenceDatastoreManager.d.ts.map +1 -1
- package/lib/runtime/presenceDatastoreManager.js.map +1 -1
- package/lib/runtime/presenceManager.js.map +1 -1
- package/package.json +15 -15
- package/dist/runtime/test/presenceDatastoreManager.spec.js +0 -618
- package/dist/runtime/test/presenceDatastoreManager.spec.js.map +0 -1
- package/dist/runtime/test/presenceManager.spec.js +0 -651
- package/dist/runtime/test/presenceManager.spec.js.map +0 -1
- package/dist/states/test/batching.spec.js +0 -843
- package/dist/states/test/batching.spec.js.map +0 -1
- package/dist/states/test/broadcastControlsTests.js +0 -60
- package/dist/states/test/broadcastControlsTests.js.map +0 -1
- package/dist/states/test/eventing.spec.js +0 -576
- package/dist/states/test/eventing.spec.js.map +0 -1
- package/dist/states/test/latestMapValueManager.spec.js +0 -210
- package/dist/states/test/latestMapValueManager.spec.js.map +0 -1
- package/dist/states/test/latestValueManager.spec.js +0 -193
- package/dist/states/test/latestValueManager.spec.js.map +0 -1
- package/dist/states/test/mockEphemeralRuntime.js +0 -11
- package/dist/states/test/mockEphemeralRuntime.js.map +0 -1
- package/dist/states/test/notificationsManager.spec.js +0 -460
- package/dist/states/test/notificationsManager.spec.js.map +0 -1
- package/dist/states/test/presenceStates.spec.js +0 -73
- package/dist/states/test/presenceStates.spec.js.map +0 -1
- package/dist/states/test/schemaValidation/protocol.spec.js +0 -246
- package/dist/states/test/schemaValidation/protocol.spec.js.map +0 -1
- package/dist/states/test/schemaValidation/valueManagers.spec.js +0 -784
- package/dist/states/test/schemaValidation/valueManagers.spec.js.map +0 -1
- package/dist/states/test/testUtils.js +0 -21
- package/dist/states/test/testUtils.js.map +0 -1
- package/dist/test/mockEphemeralRuntime.js +0 -175
- package/dist/test/mockEphemeralRuntime.js.map +0 -1
- package/dist/test/testUtils.js +0 -262
- package/dist/test/testUtils.js.map +0 -1
- package/dist/test/utils/index.js +0 -27
- package/dist/test/utils/index.js.map +0 -1
- package/dist/utils/test/timerManager.spec.js +0 -93
- package/dist/utils/test/timerManager.spec.js.map +0 -1
- package/lib/runtime/test/presenceDatastoreManager.spec.js +0 -616
- package/lib/runtime/test/presenceDatastoreManager.spec.js.map +0 -1
- package/lib/runtime/test/presenceManager.spec.js +0 -649
- package/lib/runtime/test/presenceManager.spec.js.map +0 -1
- package/lib/states/test/batching.spec.js +0 -841
- package/lib/states/test/batching.spec.js.map +0 -1
- package/lib/states/test/broadcastControlsTests.js +0 -56
- package/lib/states/test/broadcastControlsTests.js.map +0 -1
- package/lib/states/test/eventing.spec.js +0 -574
- package/lib/states/test/eventing.spec.js.map +0 -1
- package/lib/states/test/latestMapValueManager.spec.js +0 -206
- package/lib/states/test/latestMapValueManager.spec.js.map +0 -1
- package/lib/states/test/latestValueManager.spec.js +0 -189
- package/lib/states/test/latestValueManager.spec.js.map +0 -1
- package/lib/states/test/mockEphemeralRuntime.js +0 -6
- package/lib/states/test/mockEphemeralRuntime.js.map +0 -1
- package/lib/states/test/notificationsManager.spec.js +0 -456
- package/lib/states/test/notificationsManager.spec.js.map +0 -1
- package/lib/states/test/presenceStates.spec.js +0 -69
- package/lib/states/test/presenceStates.spec.js.map +0 -1
- package/lib/states/test/schemaValidation/protocol.spec.js +0 -244
- package/lib/states/test/schemaValidation/protocol.spec.js.map +0 -1
- package/lib/states/test/schemaValidation/valueManagers.spec.js +0 -782
- package/lib/states/test/schemaValidation/valueManagers.spec.js.map +0 -1
- package/lib/states/test/testUtils.js +0 -6
- package/lib/states/test/testUtils.js.map +0 -1
- package/lib/test/mockEphemeralRuntime.js +0 -171
- package/lib/test/mockEphemeralRuntime.js.map +0 -1
- package/lib/test/testUtils.js +0 -251
- package/lib/test/testUtils.js.map +0 -1
- package/lib/test/utils/index.js +0 -8
- package/lib/test/utils/index.js.map +0 -1
- package/lib/utils/test/timerManager.spec.js +0 -91
- 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"]}
|