@fluid-internal/presence-runtime 2.102.0 → 2.103.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/dist/packageVersion.d.ts +1 -1
  2. package/dist/packageVersion.js +1 -1
  3. package/dist/packageVersion.js.map +1 -1
  4. package/dist/runtime/extension/containerPresence.d.ts +1 -1
  5. package/dist/runtime/presenceDatastoreManager.d.ts +2 -2
  6. package/dist/runtime/presenceDatastoreManager.d.ts.map +1 -1
  7. package/dist/runtime/presenceDatastoreManager.js.map +1 -1
  8. package/dist/runtime/presenceManager.js.map +1 -1
  9. package/lib/packageVersion.d.ts +1 -1
  10. package/lib/packageVersion.js +1 -1
  11. package/lib/packageVersion.js.map +1 -1
  12. package/lib/runtime/extension/containerPresence.d.ts +1 -1
  13. package/lib/runtime/presenceDatastoreManager.d.ts +2 -2
  14. package/lib/runtime/presenceDatastoreManager.d.ts.map +1 -1
  15. package/lib/runtime/presenceDatastoreManager.js.map +1 -1
  16. package/lib/runtime/presenceManager.js.map +1 -1
  17. package/package.json +14 -14
  18. package/dist/runtime/test/presenceDatastoreManager.spec.js +0 -618
  19. package/dist/runtime/test/presenceDatastoreManager.spec.js.map +0 -1
  20. package/dist/runtime/test/presenceManager.spec.js +0 -651
  21. package/dist/runtime/test/presenceManager.spec.js.map +0 -1
  22. package/dist/states/test/batching.spec.js +0 -843
  23. package/dist/states/test/batching.spec.js.map +0 -1
  24. package/dist/states/test/broadcastControlsTests.js +0 -60
  25. package/dist/states/test/broadcastControlsTests.js.map +0 -1
  26. package/dist/states/test/eventing.spec.js +0 -576
  27. package/dist/states/test/eventing.spec.js.map +0 -1
  28. package/dist/states/test/latestMapValueManager.spec.js +0 -210
  29. package/dist/states/test/latestMapValueManager.spec.js.map +0 -1
  30. package/dist/states/test/latestValueManager.spec.js +0 -193
  31. package/dist/states/test/latestValueManager.spec.js.map +0 -1
  32. package/dist/states/test/mockEphemeralRuntime.js +0 -11
  33. package/dist/states/test/mockEphemeralRuntime.js.map +0 -1
  34. package/dist/states/test/notificationsManager.spec.js +0 -460
  35. package/dist/states/test/notificationsManager.spec.js.map +0 -1
  36. package/dist/states/test/presenceStates.spec.js +0 -73
  37. package/dist/states/test/presenceStates.spec.js.map +0 -1
  38. package/dist/states/test/schemaValidation/protocol.spec.js +0 -246
  39. package/dist/states/test/schemaValidation/protocol.spec.js.map +0 -1
  40. package/dist/states/test/schemaValidation/valueManagers.spec.js +0 -784
  41. package/dist/states/test/schemaValidation/valueManagers.spec.js.map +0 -1
  42. package/dist/states/test/testUtils.js +0 -21
  43. package/dist/states/test/testUtils.js.map +0 -1
  44. package/dist/test/mockEphemeralRuntime.js +0 -175
  45. package/dist/test/mockEphemeralRuntime.js.map +0 -1
  46. package/dist/test/testUtils.js +0 -262
  47. package/dist/test/testUtils.js.map +0 -1
  48. package/dist/test/utils/index.js +0 -27
  49. package/dist/test/utils/index.js.map +0 -1
  50. package/dist/utils/test/timerManager.spec.js +0 -93
  51. package/dist/utils/test/timerManager.spec.js.map +0 -1
  52. package/lib/runtime/test/presenceDatastoreManager.spec.js +0 -616
  53. package/lib/runtime/test/presenceDatastoreManager.spec.js.map +0 -1
  54. package/lib/runtime/test/presenceManager.spec.js +0 -649
  55. package/lib/runtime/test/presenceManager.spec.js.map +0 -1
  56. package/lib/states/test/batching.spec.js +0 -841
  57. package/lib/states/test/batching.spec.js.map +0 -1
  58. package/lib/states/test/broadcastControlsTests.js +0 -56
  59. package/lib/states/test/broadcastControlsTests.js.map +0 -1
  60. package/lib/states/test/eventing.spec.js +0 -574
  61. package/lib/states/test/eventing.spec.js.map +0 -1
  62. package/lib/states/test/latestMapValueManager.spec.js +0 -206
  63. package/lib/states/test/latestMapValueManager.spec.js.map +0 -1
  64. package/lib/states/test/latestValueManager.spec.js +0 -189
  65. package/lib/states/test/latestValueManager.spec.js.map +0 -1
  66. package/lib/states/test/mockEphemeralRuntime.js +0 -6
  67. package/lib/states/test/mockEphemeralRuntime.js.map +0 -1
  68. package/lib/states/test/notificationsManager.spec.js +0 -456
  69. package/lib/states/test/notificationsManager.spec.js.map +0 -1
  70. package/lib/states/test/presenceStates.spec.js +0 -69
  71. package/lib/states/test/presenceStates.spec.js.map +0 -1
  72. package/lib/states/test/schemaValidation/protocol.spec.js +0 -244
  73. package/lib/states/test/schemaValidation/protocol.spec.js.map +0 -1
  74. package/lib/states/test/schemaValidation/valueManagers.spec.js +0 -782
  75. package/lib/states/test/schemaValidation/valueManagers.spec.js.map +0 -1
  76. package/lib/states/test/testUtils.js +0 -6
  77. package/lib/states/test/testUtils.js.map +0 -1
  78. package/lib/test/mockEphemeralRuntime.js +0 -171
  79. package/lib/test/mockEphemeralRuntime.js.map +0 -1
  80. package/lib/test/testUtils.js +0 -251
  81. package/lib/test/testUtils.js.map +0 -1
  82. package/lib/test/utils/index.js +0 -8
  83. package/lib/test/utils/index.js.map +0 -1
  84. package/lib/utils/test/timerManager.spec.js +0 -91
  85. package/lib/utils/test/timerManager.spec.js.map +0 -1
@@ -1,784 +0,0 @@
1
- "use strict";
2
- /*!
3
- * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
4
- * Licensed under the MIT License.
5
- */
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- const node_assert_1 = require("node:assert");
8
- const internal_1 = require("@fluidframework/test-utils/internal");
9
- const mocha_1 = require("mocha");
10
- const sinon_1 = require("sinon");
11
- const states_1 = require("@fluid-internal/presence-runtime/states");
12
- const utils_1 = require("@fluid-internal/presence-runtime/utils");
13
- const mockEphemeralRuntime_js_1 = require("../mockEphemeralRuntime.js");
14
- const testUtils_js_1 = require("../testUtils.js");
15
- const attendeeUpdate = {
16
- "clientToSessionId": {
17
- [testUtils_js_1.connectionId1]: {
18
- "rev": 0,
19
- "timestamp": 0,
20
- "value": testUtils_js_1.attendeeId1,
21
- },
22
- },
23
- };
24
- const latestUpdate = {
25
- "latest": {
26
- [testUtils_js_1.attendeeId1]: {
27
- "rev": 1,
28
- "timestamp": 0,
29
- "value": (0, utils_1.toOpaqueJson)({ x: 1, y: 1, z: 1 }),
30
- },
31
- },
32
- };
33
- const latestMapUpdate = {
34
- "latestMap": {
35
- [testUtils_js_1.attendeeId1]: {
36
- "rev": 1,
37
- "items": {
38
- "key1": {
39
- "rev": 1,
40
- "timestamp": 0,
41
- "value": (0, utils_1.toOpaqueJson)({ x: 1, y: 1, z: 1 }),
42
- },
43
- "key2": {
44
- "rev": 1,
45
- "timestamp": 0,
46
- "value": (0, utils_1.toOpaqueJson)({ x: 2, y: 2, z: 2 }),
47
- },
48
- "invalidKey": {
49
- "rev": 1,
50
- "timestamp": 0,
51
- "value": (0, utils_1.toOpaqueJson)({ x: -1, y: -1, z: -1 }),
52
- },
53
- },
54
- },
55
- },
56
- };
57
- function datastoreUpdateSignal(sendTimestamp, valueObjectName, metadata) {
58
- return {
59
- type: "Pres:DatastoreUpdate",
60
- content: {
61
- sendTimestamp,
62
- avgLatency: 20,
63
- data: {
64
- "system:presence": attendeeUpdate,
65
- "s:name:testWorkspace": {
66
- [valueObjectName]: {
67
- [testUtils_js_1.attendeeId1]: metadata,
68
- },
69
- },
70
- },
71
- },
72
- clientId: testUtils_js_1.connectionId1,
73
- };
74
- }
75
- /**
76
- * Runs a test against a validator by getting the value and matching the resulting data and validator call counts
77
- * against expectations.
78
- */
79
- function runValidatorTest(params) {
80
- const initialValue = params.getRemoteValue();
81
- node_assert_1.strict.equal(params.validatorFunction.callCount, params.expectedCallCount);
82
- node_assert_1.strict.deepEqual(initialValue, params.expectedValue);
83
- }
84
- /**
85
- * Runs a test against a validator by getting the value multiple times and verifying that the validator is not called
86
- * multiple times.
87
- */
88
- function runMultipleCallsTest(params) {
89
- // First call should invoke validator
90
- const firstValue = params.getRemoteValue();
91
- node_assert_1.strict.equal(params.validatorFunction.callCount, 1);
92
- node_assert_1.strict.deepEqual(firstValue, params.expectedValue);
93
- // Subsequent calls should not invoke validator when data is unchanged
94
- const secondValue = params.getRemoteValue();
95
- node_assert_1.strict.equal(params.validatorFunction.callCount, 1);
96
- const thirdValue = params.getRemoteValue();
97
- node_assert_1.strict.equal(params.validatorFunction.callCount, 1);
98
- node_assert_1.strict.deepEqual(secondValue, params.expectedValue);
99
- node_assert_1.strict.deepEqual(thirdValue, params.expectedValue);
100
- }
101
- (0, mocha_1.describe)("Presence/States", () => {
102
- (0, mocha_1.describe)("Runtime schema validation", () => {
103
- const afterCleanUp = [];
104
- const initialTime = 1000;
105
- function processUpdates(valueManagerUpdates) {
106
- const updates = { "system:presence": attendeeUpdate, ...valueManagerUpdates };
107
- processSignal([], {
108
- type: "Pres:DatastoreUpdate",
109
- content: {
110
- sendTimestamp: clock.now - 10,
111
- avgLatency: 20,
112
- data: updates,
113
- },
114
- clientId: "client1",
115
- }, false);
116
- }
117
- let clock;
118
- let logger;
119
- let presence;
120
- let processSignal;
121
- let runtime;
122
- let remoteAttendee;
123
- let validatorCallExpected;
124
- let point3DValidatorFunction;
125
- (0, mocha_1.before)(async () => {
126
- clock = (0, sinon_1.useFakeTimers)();
127
- });
128
- /**
129
- * This beforeEach sets up the runtime and presence objects. The `presence` object is owned by attendee2, while
130
- * attendee1 acts as a remote attendee for the purposes of the tests.
131
- */
132
- (0, mocha_1.beforeEach)(() => {
133
- logger = new internal_1.EventAndErrorTrackingLogger();
134
- runtime = new mockEphemeralRuntime_js_1.MockEphemeralRuntime(logger);
135
- clock.setSystemTime(initialTime);
136
- validatorCallExpected = true;
137
- point3DValidatorFunction = (0, testUtils_js_1.createSpiedValidator)((d) => {
138
- if (validatorCallExpected === "once") {
139
- validatorCallExpected = false;
140
- }
141
- else {
142
- (0, node_assert_1.strict)(validatorCallExpected, "point3DValidatorFunction should not be called at this time");
143
- }
144
- return typeof d === "object" ? d : undefined;
145
- });
146
- // Create Presence joining session as attendeeId-2. Tests will act as attendee2
147
- ({ presence, processSignal } = (0, testUtils_js_1.prepareConnectedPresence)(runtime, testUtils_js_1.localAttendeeId, testUtils_js_1.initialLocalClientConnectionId, clock, logger));
148
- // Pass a little time (to mimic reality)
149
- clock.tick(10);
150
- // Process remote client update signal (attendeeId-1 is then part of local client's known session).
151
- processUpdates({
152
- "s:name:testWorkspace": { ...latestUpdate, ...latestMapUpdate },
153
- });
154
- // Pass a little time (to mimic reality)
155
- clock.tick(10);
156
- // Get attendee references
157
- remoteAttendee = presence.attendees.getAttendee(testUtils_js_1.attendeeId1);
158
- });
159
- (0, mocha_1.afterEach)(function (done) {
160
- clock.reset();
161
- point3DValidatorFunction.resetHistory();
162
- // If the test passed so far, check final expectations.
163
- if (this.currentTest?.state === "passed") {
164
- (0, testUtils_js_1.assertFinalExpectations)(runtime, logger);
165
- }
166
- for (const cleanUp of afterCleanUp) {
167
- cleanUp();
168
- }
169
- afterCleanUp.length = 0;
170
- done();
171
- });
172
- (0, mocha_1.after)(() => {
173
- clock.restore();
174
- });
175
- (0, mocha_1.describe)("Latest validator", () => {
176
- let latest;
177
- /**
178
- * This beforeEach sets up the presence workspace itself and gets a reference to it. It then sets some new data as
179
- * attendee1 by processing a datastore update signal.
180
- */
181
- (0, mocha_1.beforeEach)(() => {
182
- // Setup workspace initialization signal
183
- runtime.signalsExpected.push([
184
- {
185
- type: "Pres:DatastoreUpdate",
186
- content: {
187
- sendTimestamp: clock.now,
188
- avgLatency: 10,
189
- data: {
190
- "system:presence": {
191
- "clientToSessionId": {
192
- [testUtils_js_1.initialLocalClientConnectionId]: {
193
- "rev": 0,
194
- "timestamp": initialTime,
195
- "value": testUtils_js_1.localAttendeeId,
196
- },
197
- },
198
- },
199
- "s:name:testWorkspace": {
200
- "latest": {
201
- [testUtils_js_1.localAttendeeId]: {
202
- "rev": 0,
203
- "timestamp": clock.now,
204
- "value": (0, utils_1.toOpaqueJson)({ x: 0, y: 0, z: 0 }),
205
- },
206
- },
207
- },
208
- },
209
- },
210
- },
211
- ]);
212
- const stateWorkspace = presence.states.getWorkspace("name:testWorkspace", {
213
- latest: states_1.StateFactory.latest({
214
- local: { x: 0, y: 0, z: 0 },
215
- validator: point3DValidatorFunction,
216
- settings: { allowableUpdateLatencyMs: 0 },
217
- }),
218
- });
219
- latest = stateWorkspace.states.latest;
220
- // Process a valid update signal with Point3D data
221
- processSignal([], {
222
- type: "Pres:DatastoreUpdate",
223
- content: {
224
- sendTimestamp: clock.now - 10,
225
- avgLatency: 20,
226
- data: {
227
- "system:presence": attendeeUpdate,
228
- "s:name:testWorkspace": {
229
- "latest": {
230
- [testUtils_js_1.attendeeId1]: {
231
- "rev": 2,
232
- "timestamp": clock.now - 10,
233
- "value": (0, utils_1.toOpaqueJson)({ x: 10, y: 20, z: 30 }),
234
- },
235
- },
236
- },
237
- },
238
- },
239
- clientId: "client1",
240
- }, false);
241
- });
242
- (0, mocha_1.describe)("is not called", () => {
243
- (0, mocha_1.it)("by .getRemote()", () => {
244
- // Calling getRemote should not invoke the validator (only a value read will).
245
- latest.getRemote(remoteAttendee);
246
- node_assert_1.strict.equal(point3DValidatorFunction.callCount, 0);
247
- });
248
- (0, mocha_1.it)("by .getRemotes()", () => {
249
- for (const _ of latest.getRemotes()) {
250
- node_assert_1.strict.equal(point3DValidatorFunction.callCount, 0);
251
- }
252
- });
253
- (0, mocha_1.it)("when accessing .local", () => {
254
- node_assert_1.strict.equal(point3DValidatorFunction.callCount, 0, "initial call count is wrong");
255
- node_assert_1.strict.deepEqual(latest.local, { x: 0, y: 0, z: 0 });
256
- node_assert_1.strict.equal(point3DValidatorFunction.callCount, 0, "validator was called on local data");
257
- });
258
- (0, mocha_1.it)("when remote data is updated", () => {
259
- const remoteData = latest.getRemote(remoteAttendee);
260
- // Should call validator
261
- runValidatorTest({
262
- getRemoteValue: () => remoteData.value(),
263
- expectedCallCount: 1,
264
- expectedValue: { x: 10, y: 20, z: 30 },
265
- validatorFunction: point3DValidatorFunction,
266
- });
267
- // Send updated data from remote client
268
- const timestamp = clock.now - 15;
269
- processSignal([], datastoreUpdateSignal(timestamp, "latest", {
270
- "rev": 3,
271
- timestamp,
272
- "value": (0, utils_1.toOpaqueJson)({ x: 50, y: 60, z: 70 }),
273
- }), false);
274
- // Validator is not called by remote update
275
- node_assert_1.strict.equal(point3DValidatorFunction.callCount, 1);
276
- });
277
- });
278
- (0, mocha_1.describe)("is called", () => {
279
- (0, mocha_1.it)("on first .value() call", () => {
280
- const remoteData = latest.getRemote(remoteAttendee);
281
- runValidatorTest({
282
- getRemoteValue: () => remoteData.value(),
283
- expectedCallCount: 1,
284
- expectedValue: { x: 10, y: 20, z: 30 },
285
- validatorFunction: point3DValidatorFunction,
286
- });
287
- });
288
- (0, mocha_1.it)("only once for multiple .value() calls in series and .value() always returns same value", () => {
289
- const remoteData = latest.getRemote(remoteAttendee);
290
- runMultipleCallsTest({
291
- getRemoteValue: () => remoteData.value(),
292
- expectedValue: { x: 10, y: 20, z: 30 },
293
- validatorFunction: point3DValidatorFunction,
294
- });
295
- });
296
- (0, mocha_1.it)("on .value() call after remote data has changed", () => {
297
- // Get the remote data and read it, verify that the validator is called once.
298
- const remoteData = latest.getRemote(remoteAttendee);
299
- node_assert_1.strict.deepEqual(remoteData.value(), { x: 10, y: 20, z: 30 });
300
- node_assert_1.strict.equal(point3DValidatorFunction.callCount, 1, "first call count is wrong");
301
- // Send updated data from remote client
302
- const timestamp = clock.now - 15;
303
- processSignal([], datastoreUpdateSignal(timestamp, "latest", {
304
- "rev": 3,
305
- timestamp,
306
- "value": (0, utils_1.toOpaqueJson)({ x: 50, y: 60, z: 70 }),
307
- }), false);
308
- // Reading the remote value should cause the validator to be called a second time since the data has been changed.
309
- const data2 = latest.getRemote(remoteAttendee);
310
- node_assert_1.strict.deepEqual(data2.value(), { x: 50, y: 60, z: 70 }, "updated remote value is wrong");
311
- node_assert_1.strict.equal(point3DValidatorFunction.callCount, 2, "validator should be called twice");
312
- });
313
- (0, mocha_1.it)("on .value() call when remote data changes from valid to invalid", () => {
314
- // Get the remote data and read it, verify that the validator is called once.
315
- const remoteData = latest.getRemote(remoteAttendee);
316
- node_assert_1.strict.deepEqual(remoteData.value(), { x: 10, y: 20, z: 30 });
317
- node_assert_1.strict.equal(point3DValidatorFunction.callCount, 1, "first call count is wrong");
318
- // Send invalid data from remote client
319
- const timestamp = clock.now - 15;
320
- processSignal([], datastoreUpdateSignal(timestamp, "latest", {
321
- "rev": 3,
322
- timestamp,
323
- "value": (0, utils_1.toOpaqueJson)("invalid"),
324
- }), false);
325
- // Reading the remote value should cause the validator to be called a second time and return undefined
326
- const data2 = latest.getRemote(remoteAttendee);
327
- node_assert_1.strict.equal(data2.value(), undefined, "invalid data should return undefined");
328
- node_assert_1.strict.equal(point3DValidatorFunction.callCount, 2, "validator should be called twice");
329
- });
330
- (0, mocha_1.it)("on .value() call when remote data changes from invalid to valid", () => {
331
- // First send invalid data
332
- let timestamp = clock.now - 15;
333
- processSignal([], datastoreUpdateSignal(timestamp, "latest", {
334
- "rev": 3,
335
- timestamp,
336
- "value": (0, utils_1.toOpaqueJson)("invalid"),
337
- }), false);
338
- // Get the remote data and read it, verify that the validator is called once and returns undefined
339
- const remoteData = latest.getRemote(remoteAttendee);
340
- node_assert_1.strict.equal(remoteData.value(), undefined);
341
- node_assert_1.strict.equal(point3DValidatorFunction.callCount, 1, "first call count is wrong");
342
- // Send valid data from remote client
343
- timestamp += 10;
344
- processSignal([], datastoreUpdateSignal(timestamp, "latest", {
345
- "rev": 4,
346
- timestamp,
347
- "value": (0, utils_1.toOpaqueJson)({ x: 100, y: 200, z: 300 }),
348
- }), false);
349
- // Reading the remote value should cause the validator to be called a second time and return valid data
350
- const data2 = latest.getRemote(remoteAttendee);
351
- node_assert_1.strict.deepEqual(data2.value(), { x: 100, y: 200, z: 300 }, "valid data should be returned");
352
- node_assert_1.strict.equal(point3DValidatorFunction.callCount, 2, "validator should be called twice");
353
- });
354
- (0, mocha_1.it)("on .value() call when remote data changes from invalid to invalid", () => {
355
- // First send invalid data
356
- let timestamp = clock.now - 15;
357
- processSignal([], datastoreUpdateSignal(timestamp, "latest", {
358
- "rev": 3,
359
- timestamp,
360
- "value": (0, utils_1.toOpaqueJson)("invalid"),
361
- }), false);
362
- // Get the remote data and read it, verify that the validator is called once and returns undefined
363
- const remoteData = latest.getRemote(remoteAttendee);
364
- node_assert_1.strict.equal(remoteData.value(), undefined);
365
- node_assert_1.strict.equal(point3DValidatorFunction.callCount, 1, "first call count is wrong");
366
- // Send different invalid data from remote client
367
- timestamp += 10;
368
- processSignal([], datastoreUpdateSignal(timestamp, "latest", {
369
- "rev": 4,
370
- timestamp,
371
- "value": (0, utils_1.toOpaqueJson)("also-invalid"),
372
- }), false);
373
- // Reading the remote value should cause the validator to be called a second time and still return undefined
374
- const data2 = latest.getRemote(remoteAttendee);
375
- node_assert_1.strict.equal(data2.value(), undefined, "invalid data should return undefined");
376
- node_assert_1.strict.equal(point3DValidatorFunction.callCount, 2, "validator should be called twice");
377
- });
378
- });
379
- });
380
- (0, mocha_1.describe)("LatestMap with validation", () => {
381
- let latestMap;
382
- let keyValidatorCallExpectedCount;
383
- function keyValidatorFunction(key) {
384
- (0, node_assert_1.strict)(keyValidatorCallExpectedCount > 0, "keyValidatorFunction should not be called at this time");
385
- keyValidatorCallExpectedCount--;
386
- return key.startsWith("key");
387
- }
388
- /**
389
- * This beforeEach sets up the presence workspace itself and gets a
390
- * reference to it.
391
- */
392
- (0, mocha_1.beforeEach)(() => {
393
- keyValidatorCallExpectedCount = 0;
394
- // workspace setup's initialization signal
395
- runtime.signalsExpected.push([
396
- {
397
- "type": "Pres:DatastoreUpdate",
398
- "content": {
399
- "sendTimestamp": clock.now,
400
- "avgLatency": 10,
401
- "data": {
402
- "system:presence": {
403
- "clientToSessionId": {
404
- [testUtils_js_1.initialLocalClientConnectionId]: {
405
- "rev": 0,
406
- "timestamp": initialTime,
407
- "value": testUtils_js_1.localAttendeeId,
408
- },
409
- },
410
- },
411
- "s:name:testWorkspace": {
412
- "latestMap": {
413
- [testUtils_js_1.localAttendeeId]: {
414
- "rev": 0,
415
- "items": {
416
- "key1": {
417
- "rev": 0,
418
- "timestamp": clock.now,
419
- "value": (0, utils_1.toOpaqueJson)({ "x": 0, "y": 0, "z": 0 }),
420
- },
421
- "key2": {
422
- "rev": 0,
423
- "timestamp": clock.now,
424
- "value": (0, utils_1.toOpaqueJson)({ "x": 0, "y": 0, "z": 0 }),
425
- },
426
- },
427
- },
428
- },
429
- },
430
- },
431
- },
432
- },
433
- ]);
434
- const stateWorkspace = presence.states.getWorkspace("name:testWorkspace", {
435
- latestMap: states_1.StateFactory.latestMap({
436
- local: { "key1": { x: 0, y: 0, z: 0 }, "key2": { x: 0, y: 0, z: 0 } },
437
- validator: point3DValidatorFunction,
438
- keyValidator: keyValidatorFunction,
439
- settings: { allowableUpdateLatencyMs: 0 },
440
- }),
441
- });
442
- latestMap = stateWorkspace.states.latestMap;
443
- });
444
- function sendInvalidData(key = "key1") {
445
- keyValidatorCallExpectedCount = 1;
446
- const timestamp = clock.now - 15;
447
- processSignal([], datastoreUpdateSignal(timestamp, "latestMap", {
448
- "rev": 2,
449
- "items": {
450
- [key]: {
451
- "rev": 2,
452
- timestamp,
453
- "value": (0, utils_1.toOpaqueJson)("invalid"),
454
- },
455
- },
456
- }), false);
457
- node_assert_1.strict.equal(keyValidatorCallExpectedCount, 0);
458
- }
459
- (0, mocha_1.describe)("no validator is called", () => {
460
- (0, mocha_1.beforeEach)(() => {
461
- validatorCallExpected = false;
462
- });
463
- (0, mocha_1.it)("when reading local key value", () => {
464
- // Act
465
- const localData = latestMap.local.get("key1");
466
- // Verify
467
- node_assert_1.strict.equal(point3DValidatorFunction.callCount, 0);
468
- // double check local data
469
- node_assert_1.strict.deepEqual(localData, { x: 0, y: 0, z: 0 });
470
- });
471
- (0, mocha_1.it)("when writing local key value", () => {
472
- // Setup
473
- runtime.signalsExpected.push([
474
- {
475
- "type": "Pres:DatastoreUpdate",
476
- "content": {
477
- "sendTimestamp": clock.now,
478
- "avgLatency": 10,
479
- "data": {
480
- "system:presence": {
481
- "clientToSessionId": {
482
- [testUtils_js_1.initialLocalClientConnectionId]: {
483
- "rev": 0,
484
- "timestamp": initialTime,
485
- "value": testUtils_js_1.localAttendeeId,
486
- },
487
- },
488
- },
489
- "s:name:testWorkspace": {
490
- "latestMap": {
491
- [testUtils_js_1.localAttendeeId]: {
492
- "rev": 1,
493
- "items": {
494
- "key1": {
495
- "rev": 1,
496
- "timestamp": clock.now,
497
- "value": (0, utils_1.toOpaqueJson)({ "x": 0, "y": 1, "z": 2 }),
498
- },
499
- },
500
- },
501
- },
502
- },
503
- },
504
- },
505
- },
506
- ]);
507
- // Act
508
- latestMap.local.set("key1", { x: 0, y: 1, z: 2 });
509
- // Verify
510
- node_assert_1.strict.equal(point3DValidatorFunction.callCount, 0);
511
- });
512
- });
513
- (0, mocha_1.it)("update with invalid key invokes key validator per key and does not raise events", () => {
514
- // Setup
515
- for (const event of [
516
- "remoteUpdated",
517
- "remoteItemUpdated",
518
- "remoteItemRemoved",
519
- ]) {
520
- afterCleanUp.push(latestMap.events.on(event, () => {
521
- node_assert_1.strict.fail(`${event} event should not be raised for invalid key`);
522
- }));
523
- }
524
- keyValidatorCallExpectedCount = 1;
525
- // Act
526
- sendInvalidData("invalidKey");
527
- // Verify
528
- node_assert_1.strict.equal(keyValidatorCallExpectedCount, 0); // all expected calls were made
529
- node_assert_1.strict.equal(point3DValidatorFunction.callCount, 0);
530
- });
531
- /**
532
- * Sets validator call expectations and gets remote value data.
533
- * @returns `latestMap.getRemote(remoteAttendee)`
534
- * @remarks
535
- * `validatorCallExpected` will be `false` and `keyValidatorCallExpectedCount`
536
- * will be `0` after the call.
537
- */
538
- function getRemoteValue() {
539
- validatorCallExpected = false;
540
- keyValidatorCallExpectedCount = 3;
541
- const remoteData = latestMap.getRemote(remoteAttendee);
542
- node_assert_1.strict.equal(keyValidatorCallExpectedCount, 0);
543
- return remoteData;
544
- }
545
- (0, mocha_1.it)(".getRemote call invokes key validator per key but not value validator", () => {
546
- // Setup and Act
547
- getRemoteValue();
548
- // Verify
549
- node_assert_1.strict.equal(keyValidatorCallExpectedCount, 0); // all expected calls were made
550
- node_assert_1.strict.equal(point3DValidatorFunction.callCount, 0);
551
- });
552
- (0, mocha_1.describe)("remote value map", () => {
553
- (0, mocha_1.it)(".get() does not call any validator", () => {
554
- // Setup
555
- const remoteData = getRemoteValue();
556
- // Act
557
- remoteData.get("key1");
558
- // Verify
559
- node_assert_1.strict.equal(point3DValidatorFunction.callCount, 0);
560
- });
561
- (0, mocha_1.it)(".forEach() iteration does not call any validator", () => {
562
- // Setup
563
- const remoteData = getRemoteValue();
564
- let counter = 0;
565
- const expectedValues = [
566
- ["key1", { x: 1, y: 1, z: 1 }],
567
- ["key2", { x: 2, y: 2, z: 2 }],
568
- ];
569
- // Act
570
- // eslint-disable-next-line unicorn/no-array-for-each -- forEach is being tested here
571
- remoteData.forEach((_value, key) => {
572
- // Verify
573
- node_assert_1.strict.equal(point3DValidatorFunction.callCount, 0, "call count is wrong");
574
- node_assert_1.strict.equal(key, expectedValues[counter][0]);
575
- counter++;
576
- });
577
- // Make sure forEach iterated through all keys
578
- node_assert_1.strict.equal(counter, expectedValues.length, "counter should match expected values length");
579
- });
580
- (0, mocha_1.describe)("value validator is called", () => {
581
- for (const { desc, setup, expectedValue } of [
582
- {
583
- desc: "for valid value",
584
- setup: () => { },
585
- expectedValue: { x: 1, y: 1, z: 1 },
586
- },
587
- {
588
- desc: "for invalid value",
589
- setup: sendInvalidData,
590
- expectedValue: undefined,
591
- },
592
- ]) {
593
- (0, mocha_1.it)(`once when key.value() is called ${desc}`, () => {
594
- // Setup
595
- setup();
596
- const remoteData = getRemoteValue();
597
- validatorCallExpected = "once";
598
- // Act
599
- runValidatorTest({
600
- getRemoteValue: () => remoteData.get("key1")?.value(),
601
- expectedCallCount: 1,
602
- expectedValue,
603
- validatorFunction: point3DValidatorFunction,
604
- });
605
- });
606
- (0, mocha_1.it)(`only once for multiple key.value() calls in series and .value() always returned same result ${desc}`, () => {
607
- // Setup
608
- setup();
609
- const remoteData = getRemoteValue();
610
- validatorCallExpected = "once";
611
- // Act
612
- runMultipleCallsTest({
613
- getRemoteValue: () => remoteData.get("key1")?.value(),
614
- expectedValue,
615
- validatorFunction: point3DValidatorFunction,
616
- });
617
- });
618
- (0, mocha_1.it)(`exactly once for each value's .value() calls in .forEach() and .value() always returns same result ${desc}`, () => {
619
- // Setup
620
- setup();
621
- const remoteData = getRemoteValue();
622
- let counter = 0;
623
- const expectedValues = [
624
- // only key1 value might be altered by the setup function
625
- ["key1", expectedValue],
626
- // key2 value will always be the valid
627
- ["key2", { x: 2, y: 2, z: 2 }],
628
- ];
629
- // Act
630
- // eslint-disable-next-line unicorn/no-array-for-each -- forEach is being tested here
631
- remoteData.forEach((value, key) => {
632
- node_assert_1.strict.equal(key, expectedValues[counter][0]);
633
- // reset call expectations/count for each iteration
634
- validatorCallExpected = "once";
635
- point3DValidatorFunction.callCount = 0;
636
- // Act - first call
637
- const valueData = value?.value();
638
- // Verify
639
- node_assert_1.strict.equal(point3DValidatorFunction.callCount, 1, "validator was not called");
640
- // double check value
641
- node_assert_1.strict.deepEqual(valueData, expectedValues[counter][1], `value at key "${key}" is wrong`);
642
- // Act - second call
643
- // Access value a second time; should not affect validator call count
644
- const valueDataRedux = value?.value();
645
- // Verify
646
- node_assert_1.strict.equal(point3DValidatorFunction.callCount, 1, "validator was called a second time");
647
- node_assert_1.strict.strictEqual(valueDataRedux, valueData, `value at key "${key}" is wrong`);
648
- counter++;
649
- });
650
- // Make sure forEach iterated through all keys
651
- node_assert_1.strict.equal(counter, expectedValues.length, "counter should match expected values length");
652
- });
653
- }
654
- for (const { desc, setup, expectedInitialValue, newData, expectedValue } of [
655
- {
656
- desc: "from valid to different valid value",
657
- setup: () => { },
658
- expectedInitialValue: { x: 1, y: 1, z: 1 },
659
- newData: { x: 4, y: 4, z: 4 },
660
- expectedValue: { x: 4, y: 4, z: 4 },
661
- },
662
- {
663
- desc: "from valid to same valid value",
664
- setup: () => { },
665
- expectedInitialValue: { x: 1, y: 1, z: 1 },
666
- newData: { x: 1, y: 1, z: 1 },
667
- expectedValue: { x: 1, y: 1, z: 1 },
668
- },
669
- {
670
- desc: "from valid to invalid value",
671
- setup: () => { },
672
- expectedInitialValue: { x: 1, y: 1, z: 1 },
673
- newData: "invalid",
674
- expectedValue: undefined,
675
- },
676
- {
677
- desc: "from invalid to valid value",
678
- setup: sendInvalidData,
679
- expectedInitialValue: undefined,
680
- newData: { x: 4, y: 4, z: 4 },
681
- expectedValue: { x: 4, y: 4, z: 4 },
682
- },
683
- {
684
- desc: "from invalid to invalid value",
685
- setup: sendInvalidData,
686
- expectedInitialValue: undefined,
687
- newData: "invalid",
688
- expectedValue: undefined,
689
- },
690
- ]) {
691
- (0, mocha_1.it)(`during .value() call after remote key data has changed ${desc}`, () => {
692
- // Setup
693
- setup();
694
- const originalMap = getRemoteValue();
695
- validatorCallExpected = "once";
696
- // Get the remote data and read it, expect that the validator is called once.
697
- const key1Value = originalMap.get("key1")?.value();
698
- node_assert_1.strict.equal(point3DValidatorFunction.callCount, 1, "first call count is wrong");
699
- node_assert_1.strict.deepEqual(key1Value, expectedInitialValue);
700
- // Reset call count for next verification
701
- point3DValidatorFunction.callCount = 0;
702
- // Process updated key data from remote client
703
- keyValidatorCallExpectedCount = 1;
704
- const timestamp = clock.now - 15;
705
- processSignal([], datastoreUpdateSignal(timestamp, "latestMap", {
706
- "rev": 3,
707
- "items": {
708
- "key1": {
709
- "rev": 3,
710
- timestamp,
711
- "value": (0, utils_1.toOpaqueJson)(newData),
712
- },
713
- },
714
- }), false);
715
- node_assert_1.strict.equal(keyValidatorCallExpectedCount, 0);
716
- // Verify no call yet
717
- node_assert_1.strict.equal(point3DValidatorFunction.callCount, 0, "call count after update is wrong");
718
- // Reading the remote value should cause the validator to be
719
- // called since the data has been changed.
720
- const updatedMap = getRemoteValue();
721
- validatorCallExpected = "once";
722
- // Act - read updated key value
723
- const updatedKey1Value = updatedMap.get("key1")?.value();
724
- // Verify
725
- node_assert_1.strict.equal(point3DValidatorFunction.callCount, 1, "validator should be called twice");
726
- node_assert_1.strict.deepEqual(updatedKey1Value, expectedValue, "updated remote key value is wrong");
727
- });
728
- }
729
- });
730
- });
731
- // Note this block is after "value validator is called" as it is only valid when those tests are passing.
732
- (0, mocha_1.describe)("no validator is called", () => {
733
- (0, mocha_1.it)("during .value() call for unchanged keys", () => {
734
- // Setup
735
- keyValidatorCallExpectedCount = 3;
736
- const originalMap = latestMap.getRemote(remoteAttendee);
737
- node_assert_1.strict.equal(keyValidatorCallExpectedCount, 0);
738
- validatorCallExpected = "once";
739
- // Read key1 value - should call validator once
740
- const key1Value = originalMap.get("key1")?.value();
741
- node_assert_1.strict.equal(point3DValidatorFunction.callCount, 1, "validator should be called once for key1");
742
- node_assert_1.strict.deepEqual(key1Value, { x: 1, y: 1, z: 1 });
743
- // Update key2 (different key) with new data, keeping key1 unchanged
744
- keyValidatorCallExpectedCount = 1;
745
- const timestamp = clock.now - 15;
746
- processSignal([], datastoreUpdateSignal(timestamp, "latestMap", {
747
- "rev": 2,
748
- "items": {
749
- "key2": {
750
- "rev": 2,
751
- timestamp,
752
- "value": (0, utils_1.toOpaqueJson)({ "x": 4, "y": 4, "z": 4 }),
753
- },
754
- },
755
- }), false);
756
- node_assert_1.strict.equal(keyValidatorCallExpectedCount, 0);
757
- const updatedMap = getRemoteValue();
758
- const key1Redux = updatedMap.get("key1");
759
- node_assert_1.strict.ok(key1Redux);
760
- node_assert_1.strict.equal(keyValidatorCallExpectedCount, 0);
761
- node_assert_1.strict.equal(point3DValidatorFunction.callCount, 1);
762
- // Act & Verify
763
- // Read key1 value (again) but from updated map - should NOT call validator again since key1 data hasn't changed
764
- const key1ValueRedux = key1Redux.value();
765
- node_assert_1.strict.equal(point3DValidatorFunction.callCount, 1, "validator should still be called only once for key1");
766
- node_assert_1.strict.strictEqual(key1ValueRedux, key1Value, "key1 value should remain unchanged");
767
- // Test verification
768
- validatorCallExpected = true;
769
- point3DValidatorFunction.callCount = 0;
770
- // key2 should have been updated; so, reading key2 value from
771
- // original map and updated map should both result in call
772
- // count increases. Also check for updated value.
773
- let key2Value = originalMap.get("key2")?.value();
774
- node_assert_1.strict.equal(point3DValidatorFunction.callCount, 1, "validator should be called once for original key2 value read");
775
- node_assert_1.strict.deepEqual(key2Value, { "x": 2, "y": 2, "z": 2 }, "key2 value from original map should be unchanged");
776
- key2Value = updatedMap.get("key2")?.value();
777
- node_assert_1.strict.equal(point3DValidatorFunction.callCount, 2, "validator should be called second time for updated key2 value read");
778
- node_assert_1.strict.deepEqual(key2Value, { "x": 4, "y": 4, "z": 4 }, "key2 should have updated value");
779
- });
780
- });
781
- });
782
- });
783
- });
784
- //# sourceMappingURL=valueManagers.spec.js.map